mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-02-19 00:18:56 +01:00
Update Task object to handle translation keys with subs
This commit is contained in:
parent
bb481ccfb4
commit
8512d5e693
@ -301,7 +301,12 @@ class FolderWatcher extends EventEmitter {
|
|||||||
libraryId,
|
libraryId,
|
||||||
libraryName: libwatcher.name
|
libraryName: libwatcher.name
|
||||||
}
|
}
|
||||||
this.pendingTask = TaskManager.createAndAddTask('watcher-scan', `Scanning file changes in "${libwatcher.name}"`, null, true, taskData)
|
const taskTitleString = {
|
||||||
|
text: `Scanning file changes in "${libwatcher.name}"`,
|
||||||
|
key: 'MessageTaskScanningFileChanges',
|
||||||
|
subs: [libwatcher.name]
|
||||||
|
}
|
||||||
|
this.pendingTask = TaskManager.createAndAddTask('watcher-scan', taskTitleString, null, true, taskData)
|
||||||
}
|
}
|
||||||
this.pendingFileUpdates.push({
|
this.pendingFileUpdates.push({
|
||||||
path,
|
path,
|
||||||
|
@ -40,7 +40,11 @@ class AbMergeManager {
|
|||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
cancelEncode(task) {
|
cancelEncode(task) {
|
||||||
task.setFailed('Task canceled by user')
|
const taskFailedString = {
|
||||||
|
text: 'Task canceled by user',
|
||||||
|
key: 'MessageTaskCanceledByUser'
|
||||||
|
}
|
||||||
|
task.setFailed(taskFailedString)
|
||||||
return this.removeTask(task, true)
|
return this.removeTask(task, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,8 +80,17 @@ class AbMergeManager {
|
|||||||
duration: libraryItem.media.duration,
|
duration: libraryItem.media.duration,
|
||||||
encodeOptions: options
|
encodeOptions: options
|
||||||
}
|
}
|
||||||
const taskDescription = `Encoding audiobook "${libraryItem.media.metadata.title}" into a single m4b file.`
|
|
||||||
task.setData('encode-m4b', 'Encoding M4b', taskDescription, false, taskData)
|
const taskTitleString = {
|
||||||
|
text: 'Encoding M4b',
|
||||||
|
key: 'MessageTaskEncodingM4b'
|
||||||
|
}
|
||||||
|
const taskDescriptionString = {
|
||||||
|
text: `Encoding audiobook "${libraryItem.media.metadata.title}" into a single m4b file.`,
|
||||||
|
key: 'MessageTaskEncodingM4bDescription',
|
||||||
|
subs: [libraryItem.media.metadata.title]
|
||||||
|
}
|
||||||
|
task.setData('encode-m4b', taskTitleString, taskDescriptionString, false, taskData)
|
||||||
TaskManager.addTask(task)
|
TaskManager.addTask(task)
|
||||||
Logger.info(`Start m4b encode for ${libraryItem.id} - TaskId: ${task.id}`)
|
Logger.info(`Start m4b encode for ${libraryItem.id} - TaskId: ${task.id}`)
|
||||||
|
|
||||||
@ -98,7 +111,11 @@ class AbMergeManager {
|
|||||||
// Make sure the target directory is writable
|
// Make sure the target directory is writable
|
||||||
if (!(await isWritable(task.data.libraryItemDir))) {
|
if (!(await isWritable(task.data.libraryItemDir))) {
|
||||||
Logger.error(`[AbMergeManager] Target directory is not writable: ${task.data.libraryItemDir}`)
|
Logger.error(`[AbMergeManager] Target directory is not writable: ${task.data.libraryItemDir}`)
|
||||||
task.setFailed('Target directory is not writable')
|
const taskFailedString = {
|
||||||
|
text: 'Target directory is not writable',
|
||||||
|
key: 'MessageTaskTargetDirectoryNotWritable'
|
||||||
|
}
|
||||||
|
task.setFailed(taskFailedString)
|
||||||
this.removeTask(task, true)
|
this.removeTask(task, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -106,7 +123,11 @@ class AbMergeManager {
|
|||||||
// Create ffmetadata file
|
// Create ffmetadata file
|
||||||
if (!(await ffmpegHelpers.writeFFMetadataFile(task.data.ffmetadataObject, task.data.chapters, task.data.ffmetadataPath))) {
|
if (!(await ffmpegHelpers.writeFFMetadataFile(task.data.ffmetadataObject, task.data.chapters, task.data.ffmetadataPath))) {
|
||||||
Logger.error(`[AudioMetadataManager] Failed to write ffmetadata file for audiobook "${task.data.libraryItemId}"`)
|
Logger.error(`[AudioMetadataManager] Failed to write ffmetadata file for audiobook "${task.data.libraryItemId}"`)
|
||||||
task.setFailed('Failed to write metadata file.')
|
const taskFailedString = {
|
||||||
|
text: 'Failed to write metadata file',
|
||||||
|
key: 'MessageTaskFailedToWriteMetadataFile'
|
||||||
|
}
|
||||||
|
task.setFailed(taskFailedString)
|
||||||
this.removeTask(task, true)
|
this.removeTask(task, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -137,7 +158,11 @@ class AbMergeManager {
|
|||||||
Logger.info(`[AbMergeManager] Task cancelled ${task.id}`)
|
Logger.info(`[AbMergeManager] Task cancelled ${task.id}`)
|
||||||
} else {
|
} else {
|
||||||
Logger.error(`[AbMergeManager] mergeAudioFiles failed`, error)
|
Logger.error(`[AbMergeManager] mergeAudioFiles failed`, error)
|
||||||
task.setFailed('Failed to merge audio files')
|
const taskFailedString = {
|
||||||
|
text: 'Failed to merge audio files',
|
||||||
|
key: 'MessageTaskFailedToMergeAudioFiles'
|
||||||
|
}
|
||||||
|
task.setFailed(taskFailedString)
|
||||||
this.removeTask(task, true)
|
this.removeTask(task, true)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -164,7 +189,11 @@ class AbMergeManager {
|
|||||||
Logger.info(`[AbMergeManager] Task cancelled ${task.id}`)
|
Logger.info(`[AbMergeManager] Task cancelled ${task.id}`)
|
||||||
} else {
|
} else {
|
||||||
Logger.error(`[AbMergeManager] Failed to write metadata to file "${task.data.tempFilepath}"`)
|
Logger.error(`[AbMergeManager] Failed to write metadata to file "${task.data.tempFilepath}"`)
|
||||||
task.setFailed('Failed to write metadata to m4b file')
|
const taskFailedString = {
|
||||||
|
text: 'Failed to write metadata to m4b file',
|
||||||
|
key: 'MessageTaskFailedToWriteMetadataToM4bFile'
|
||||||
|
}
|
||||||
|
task.setFailed(taskFailedString)
|
||||||
this.removeTask(task, true)
|
this.removeTask(task, true)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -196,7 +225,11 @@ class AbMergeManager {
|
|||||||
await fs.remove(task.data.tempFilepath)
|
await fs.remove(task.data.tempFilepath)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Logger.error(`[AbMergeManager] Failed to move m4b from ${task.data.tempFilepath} to ${task.data.targetFilepath}`, err)
|
Logger.error(`[AbMergeManager] Failed to move m4b from ${task.data.tempFilepath} to ${task.data.targetFilepath}`, err)
|
||||||
task.setFailed('Failed to move m4b file')
|
const taskFailedString = {
|
||||||
|
text: 'Failed to move m4b file',
|
||||||
|
key: 'MessageTaskFailedToMoveM4bFile'
|
||||||
|
}
|
||||||
|
task.setFailed(taskFailedString)
|
||||||
this.removeTask(task, true)
|
this.removeTask(task, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -97,8 +97,17 @@ class AudioMetadataMangaer {
|
|||||||
},
|
},
|
||||||
duration: libraryItem.media.duration
|
duration: libraryItem.media.duration
|
||||||
}
|
}
|
||||||
const taskDescription = `Embedding metadata in audiobook "${libraryItem.media.metadata.title}".`
|
|
||||||
task.setData('embed-metadata', 'Embedding Metadata', taskDescription, false, taskData)
|
const taskTitleString = {
|
||||||
|
text: 'Embedding Metadata',
|
||||||
|
key: 'MessageTaskEmbeddingMetadata'
|
||||||
|
}
|
||||||
|
const taskDescriptionString = {
|
||||||
|
text: `Embedding metadata in audiobook "${libraryItem.media.metadata.title}".`,
|
||||||
|
key: 'MessageTaskEmbeddingMetadataDescription',
|
||||||
|
subs: [libraryItem.media.metadata.title]
|
||||||
|
}
|
||||||
|
task.setData('embed-metadata', taskTitleString, taskDescriptionString, false, taskData)
|
||||||
|
|
||||||
if (this.tasksRunning.length >= this.MAX_CONCURRENT_TASKS) {
|
if (this.tasksRunning.length >= this.MAX_CONCURRENT_TASKS) {
|
||||||
Logger.info(`[AudioMetadataManager] Queueing embed metadata for audiobook "${libraryItem.media.metadata.title}"`)
|
Logger.info(`[AudioMetadataManager] Queueing embed metadata for audiobook "${libraryItem.media.metadata.title}"`)
|
||||||
@ -123,7 +132,7 @@ class AudioMetadataMangaer {
|
|||||||
Logger.debug(`[AudioMetadataManager] Target directory ${task.data.libraryItemDir} writable: ${targetDirWritable}`)
|
Logger.debug(`[AudioMetadataManager] Target directory ${task.data.libraryItemDir} writable: ${targetDirWritable}`)
|
||||||
if (!targetDirWritable) {
|
if (!targetDirWritable) {
|
||||||
Logger.error(`[AudioMetadataManager] Target directory is not writable: ${task.data.libraryItemDir}`)
|
Logger.error(`[AudioMetadataManager] Target directory is not writable: ${task.data.libraryItemDir}`)
|
||||||
task.setFailed('Target directory is not writable')
|
task.setFailedText('Target directory is not writable')
|
||||||
this.handleTaskFinished(task)
|
this.handleTaskFinished(task)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -134,7 +143,7 @@ class AudioMetadataMangaer {
|
|||||||
await fs.access(af.path, fs.constants.W_OK)
|
await fs.access(af.path, fs.constants.W_OK)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Logger.error(`[AudioMetadataManager] Audio file is not writable: ${af.path}`)
|
Logger.error(`[AudioMetadataManager] Audio file is not writable: ${af.path}`)
|
||||||
task.setFailed(`Audio file "${Path.basename(af.path)}" is not writable`)
|
task.setFailedText(`Audio file "${Path.basename(af.path)}" is not writable`)
|
||||||
this.handleTaskFinished(task)
|
this.handleTaskFinished(task)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -148,7 +157,7 @@ class AudioMetadataMangaer {
|
|||||||
cacheDirCreated = true
|
cacheDirCreated = true
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Logger.error(`[AudioMetadataManager] Failed to create cache directory ${task.data.itemCachePath}`, err)
|
Logger.error(`[AudioMetadataManager] Failed to create cache directory ${task.data.itemCachePath}`, err)
|
||||||
task.setFailed('Failed to create cache directory')
|
task.setFailedText('Failed to create cache directory')
|
||||||
this.handleTaskFinished(task)
|
this.handleTaskFinished(task)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -159,7 +168,7 @@ class AudioMetadataMangaer {
|
|||||||
const success = await ffmpegHelpers.writeFFMetadataFile(task.data.metadataObject, task.data.chapters, ffmetadataPath)
|
const success = await ffmpegHelpers.writeFFMetadataFile(task.data.metadataObject, task.data.chapters, ffmetadataPath)
|
||||||
if (!success) {
|
if (!success) {
|
||||||
Logger.error(`[AudioMetadataManager] Failed to write ffmetadata file for audiobook "${task.data.libraryItemId}"`)
|
Logger.error(`[AudioMetadataManager] Failed to write ffmetadata file for audiobook "${task.data.libraryItemId}"`)
|
||||||
task.setFailed('Failed to write metadata file.')
|
task.setFailedText('Failed to write metadata file.')
|
||||||
this.handleTaskFinished(task)
|
this.handleTaskFinished(task)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -181,7 +190,7 @@ class AudioMetadataMangaer {
|
|||||||
Logger.debug(`[AudioMetadataManager] Backed up audio file at "${backupFilePath}"`)
|
Logger.debug(`[AudioMetadataManager] Backed up audio file at "${backupFilePath}"`)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Logger.error(`[AudioMetadataManager] Failed to backup audio file "${af.path}"`, err)
|
Logger.error(`[AudioMetadataManager] Failed to backup audio file "${af.path}"`, err)
|
||||||
task.setFailed(`Failed to backup audio file "${Path.basename(af.path)}"`)
|
task.setFailedText(`Failed to backup audio file "${Path.basename(af.path)}"`)
|
||||||
this.handleTaskFinished(task)
|
this.handleTaskFinished(task)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -195,7 +204,7 @@ class AudioMetadataMangaer {
|
|||||||
Logger.info(`[AudioMetadataManager] Successfully tagged audio file "${af.path}"`)
|
Logger.info(`[AudioMetadataManager] Successfully tagged audio file "${af.path}"`)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Logger.error(`[AudioMetadataManager] Failed to tag audio file "${af.path}"`, err)
|
Logger.error(`[AudioMetadataManager] Failed to tag audio file "${af.path}"`, err)
|
||||||
task.setFailed(`Failed to tag audio file "${Path.basename(af.path)}"`)
|
task.setFailedText(`Failed to tag audio file "${Path.basename(af.path)}"`)
|
||||||
this.handleTaskFinished(task)
|
this.handleTaskFinished(task)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -71,12 +71,20 @@ class PodcastManager {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const taskDescription = `Downloading episode "${podcastEpisodeDownload.podcastEpisode.title}".`
|
|
||||||
const taskData = {
|
const taskData = {
|
||||||
libraryId: podcastEpisodeDownload.libraryId,
|
libraryId: podcastEpisodeDownload.libraryId,
|
||||||
libraryItemId: podcastEpisodeDownload.libraryItemId
|
libraryItemId: podcastEpisodeDownload.libraryItemId
|
||||||
}
|
}
|
||||||
const task = TaskManager.createAndAddTask('download-podcast-episode', 'Downloading Episode', taskDescription, false, taskData)
|
const taskTitleString = {
|
||||||
|
text: 'Downloading episode',
|
||||||
|
key: 'MessageDownloadingEpisode'
|
||||||
|
}
|
||||||
|
const taskDescriptionString = {
|
||||||
|
text: `Downloading episode "${podcastEpisodeDownload.podcastEpisode.title}".`,
|
||||||
|
key: 'MessageTaskDownloadingEpisodeDescription',
|
||||||
|
subs: [podcastEpisodeDownload.podcastEpisode.title]
|
||||||
|
}
|
||||||
|
const task = TaskManager.createAndAddTask('download-podcast-episode', taskTitleString, taskDescriptionString, false, taskData)
|
||||||
|
|
||||||
SocketAuthority.emitter('episode_download_started', podcastEpisodeDownload.toJSONForClient())
|
SocketAuthority.emitter('episode_download_started', podcastEpisodeDownload.toJSONForClient())
|
||||||
this.currentDownload = podcastEpisodeDownload
|
this.currentDownload = podcastEpisodeDownload
|
||||||
@ -119,14 +127,14 @@ class PodcastManager {
|
|||||||
if (!success) {
|
if (!success) {
|
||||||
await fs.remove(this.currentDownload.targetPath)
|
await fs.remove(this.currentDownload.targetPath)
|
||||||
this.currentDownload.setFinished(false)
|
this.currentDownload.setFinished(false)
|
||||||
task.setFailed('Failed to download episode')
|
task.setFailedText('Failed to download episode')
|
||||||
} else {
|
} else {
|
||||||
Logger.info(`[PodcastManager] Successfully downloaded podcast episode "${this.currentDownload.podcastEpisode.title}"`)
|
Logger.info(`[PodcastManager] Successfully downloaded podcast episode "${this.currentDownload.podcastEpisode.title}"`)
|
||||||
this.currentDownload.setFinished(true)
|
this.currentDownload.setFinished(true)
|
||||||
task.setFinished()
|
task.setFinished()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
task.setFailed('Failed to download episode')
|
task.setFailedText('Failed to download episode')
|
||||||
this.currentDownload.setFinished(false)
|
this.currentDownload.setFinished(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,13 +415,35 @@ class PodcastManager {
|
|||||||
* @param {import('../managers/CronManager')} cronManager
|
* @param {import('../managers/CronManager')} cronManager
|
||||||
*/
|
*/
|
||||||
async createPodcastsFromFeedUrls(rssFeedUrls, folder, autoDownloadEpisodes, cronManager) {
|
async createPodcastsFromFeedUrls(rssFeedUrls, folder, autoDownloadEpisodes, cronManager) {
|
||||||
const task = TaskManager.createAndAddTask('opml-import', 'OPML import', `Creating podcasts from ${rssFeedUrls.length} RSS feeds`, true, null)
|
const taskTitleString = {
|
||||||
|
text: 'OPML import',
|
||||||
|
key: 'MessageTaskOpmlImport'
|
||||||
|
}
|
||||||
|
const taskDescriptionString = {
|
||||||
|
text: `Creating podcasts from ${rssFeedUrls.length} RSS feeds`,
|
||||||
|
key: 'MessageTaskOpmlImportDescription',
|
||||||
|
subs: [rssFeedUrls.length]
|
||||||
|
}
|
||||||
|
const task = TaskManager.createAndAddTask('opml-import', taskTitleString, taskDescriptionString, true, null)
|
||||||
let numPodcastsAdded = 0
|
let numPodcastsAdded = 0
|
||||||
Logger.info(`[PodcastManager] createPodcastsFromFeedUrls: Importing ${rssFeedUrls.length} RSS feeds to folder "${folder.path}"`)
|
Logger.info(`[PodcastManager] createPodcastsFromFeedUrls: Importing ${rssFeedUrls.length} RSS feeds to folder "${folder.path}"`)
|
||||||
for (const feedUrl of rssFeedUrls) {
|
for (const feedUrl of rssFeedUrls) {
|
||||||
const feed = await getPodcastFeed(feedUrl).catch(() => null)
|
const feed = await getPodcastFeed(feedUrl).catch(() => null)
|
||||||
if (!feed?.episodes) {
|
if (!feed?.episodes) {
|
||||||
TaskManager.createAndEmitFailedTask('opml-import-feed', 'OPML import feed', `Importing RSS feed "${feedUrl}"`, 'Failed to get podcast feed')
|
const taskTitleStringFeed = {
|
||||||
|
text: 'OPML import feed',
|
||||||
|
key: 'MessageTaskOpmlImportFeed'
|
||||||
|
}
|
||||||
|
const taskDescriptionStringFeed = {
|
||||||
|
text: `Importing RSS feed "${feedUrl}"`,
|
||||||
|
key: 'MessageTaskOpmlImportFeedDescription',
|
||||||
|
subs: [feedUrl]
|
||||||
|
}
|
||||||
|
const taskErrorString = {
|
||||||
|
text: 'Failed to get podcast feed',
|
||||||
|
key: 'MessageTaskOpmlImportFeedFailed'
|
||||||
|
}
|
||||||
|
TaskManager.createAndEmitFailedTask('opml-import-feed', taskTitleStringFeed, taskDescriptionStringFeed, taskErrorString)
|
||||||
Logger.error(`[PodcastManager] createPodcastsFromFeedUrls: Failed to get podcast feed for "${feedUrl}"`)
|
Logger.error(`[PodcastManager] createPodcastsFromFeedUrls: Failed to get podcast feed for "${feedUrl}"`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -429,7 +459,20 @@ class PodcastManager {
|
|||||||
})) > 0
|
})) > 0
|
||||||
if (existingLibraryItem) {
|
if (existingLibraryItem) {
|
||||||
Logger.error(`[PodcastManager] createPodcastsFromFeedUrls: Podcast already exists at path "${podcastPath}"`)
|
Logger.error(`[PodcastManager] createPodcastsFromFeedUrls: Podcast already exists at path "${podcastPath}"`)
|
||||||
TaskManager.createAndEmitFailedTask('opml-import-feed', 'OPML import feed', `Creating podcast "${feed.metadata.title}"`, 'Podcast already exists at path')
|
const taskTitleStringFeed = {
|
||||||
|
text: 'OPML import feed',
|
||||||
|
key: 'MessageTaskOpmlImportFeed'
|
||||||
|
}
|
||||||
|
const taskDescriptionStringPodcast = {
|
||||||
|
text: `Creating podcast "${feed.metadata.title}"`,
|
||||||
|
key: 'MessageTaskOpmlImportFeedPodcastDescription',
|
||||||
|
subs: [feed.metadata.title]
|
||||||
|
}
|
||||||
|
const taskErrorString = {
|
||||||
|
text: 'Podcast already exists at path',
|
||||||
|
key: 'MessageTaskOpmlImportFeedPodcastExists'
|
||||||
|
}
|
||||||
|
TaskManager.createAndEmitFailedTask('opml-import-feed', taskTitleStringFeed, taskDescriptionStringPodcast, taskErrorString)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,7 +485,20 @@ class PodcastManager {
|
|||||||
})
|
})
|
||||||
if (!successCreatingPath) {
|
if (!successCreatingPath) {
|
||||||
Logger.error(`[PodcastManager] createPodcastsFromFeedUrls: Failed to create podcast folder at "${podcastPath}"`)
|
Logger.error(`[PodcastManager] createPodcastsFromFeedUrls: Failed to create podcast folder at "${podcastPath}"`)
|
||||||
TaskManager.createAndEmitFailedTask('opml-import-feed', 'OPML import feed', `Creating podcast "${feed.metadata.title}"`, 'Failed to create podcast folder')
|
const taskTitleStringFeed = {
|
||||||
|
text: 'OPML import feed',
|
||||||
|
key: 'MessageTaskOpmlImportFeed'
|
||||||
|
}
|
||||||
|
const taskDescriptionStringPodcast = {
|
||||||
|
text: `Creating podcast "${feed.metadata.title}"`,
|
||||||
|
key: 'MessageTaskOpmlImportFeedPodcastDescription',
|
||||||
|
subs: [feed.metadata.title]
|
||||||
|
}
|
||||||
|
const taskErrorString = {
|
||||||
|
text: 'Failed to create podcast folder',
|
||||||
|
key: 'MessageTaskOpmlImportFeedPodcastFailed'
|
||||||
|
}
|
||||||
|
TaskManager.createAndEmitFailedTask('opml-import-feed', taskTitleStringFeed, taskDescriptionStringPodcast, taskErrorString)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
const SocketAuthority = require('../SocketAuthority')
|
const SocketAuthority = require('../SocketAuthority')
|
||||||
const Task = require('../objects/Task')
|
const Task = require('../objects/Task')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef TaskString
|
||||||
|
* @property {string} text
|
||||||
|
* @property {string} key
|
||||||
|
* @property {string[]} [subs]
|
||||||
|
*/
|
||||||
|
|
||||||
class TaskManager {
|
class TaskManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
/** @type {Task[]} */
|
/** @type {Task[]} */
|
||||||
@ -33,14 +40,14 @@ class TaskManager {
|
|||||||
* Create new task and add
|
* Create new task and add
|
||||||
*
|
*
|
||||||
* @param {string} action
|
* @param {string} action
|
||||||
* @param {string} title
|
* @param {TaskString} titleString
|
||||||
* @param {string} description
|
* @param {TaskString|null} descriptionString
|
||||||
* @param {boolean} showSuccess
|
* @param {boolean} showSuccess
|
||||||
* @param {Object} [data]
|
* @param {Object} [data]
|
||||||
*/
|
*/
|
||||||
createAndAddTask(action, title, description, showSuccess, data = {}) {
|
createAndAddTask(action, titleString, descriptionString, showSuccess, data = {}) {
|
||||||
const task = new Task()
|
const task = new Task()
|
||||||
task.setData(action, title, description, showSuccess, data)
|
task.setData(action, titleString, descriptionString, showSuccess, data)
|
||||||
this.addTask(task)
|
this.addTask(task)
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
@ -49,14 +56,14 @@ class TaskManager {
|
|||||||
* Create new failed task and add
|
* Create new failed task and add
|
||||||
*
|
*
|
||||||
* @param {string} action
|
* @param {string} action
|
||||||
* @param {string} title
|
* @param {TaskString} titleString
|
||||||
* @param {string} description
|
* @param {TaskString|null} descriptionString
|
||||||
* @param {string} errorMessage
|
* @param {TaskString} errorMessageString
|
||||||
*/
|
*/
|
||||||
createAndEmitFailedTask(action, title, description, errorMessage) {
|
createAndEmitFailedTask(action, titleString, descriptionString, errorMessageString) {
|
||||||
const task = new Task()
|
const task = new Task()
|
||||||
task.setData(action, title, description, false)
|
task.setData(action, titleString, descriptionString, false)
|
||||||
task.setFailed(errorMessage)
|
task.setFailedText(errorMessageString)
|
||||||
SocketAuthority.emitter('task_started', task.toJSON())
|
SocketAuthority.emitter('task_started', task.toJSON())
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
const uuidv4 = require("uuid").v4
|
const uuidv4 = require('uuid').v4
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef TaskString
|
||||||
|
* @property {string} text
|
||||||
|
* @property {string} key
|
||||||
|
* @property {string[]} [subs]
|
||||||
|
*/
|
||||||
|
|
||||||
class Task {
|
class Task {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -11,10 +18,25 @@ class Task {
|
|||||||
|
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
this.title = null
|
this.title = null
|
||||||
|
/** @type {string} - Used for translation */
|
||||||
|
this.titleKey = null
|
||||||
|
/** @type {string[]} - Used for translation */
|
||||||
|
this.titleSubs = null
|
||||||
|
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
this.description = null
|
this.description = null
|
||||||
|
/** @type {string} - Used for translation */
|
||||||
|
this.descriptionKey = null
|
||||||
|
/** @type {string[]} - Used for translation */
|
||||||
|
this.descriptionSubs = null
|
||||||
|
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
this.error = null
|
this.error = null
|
||||||
|
/** @type {string} - Used for translation */
|
||||||
|
this.errorKey = null
|
||||||
|
/** @type {string[]} - Used for translation */
|
||||||
|
this.errorSubs = null
|
||||||
|
|
||||||
/** @type {boolean} client should keep the task visible after success */
|
/** @type {boolean} client should keep the task visible after success */
|
||||||
this.showSuccess = false
|
this.showSuccess = false
|
||||||
|
|
||||||
@ -47,30 +69,51 @@ class Task {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set initial task data
|
* Set initial task data
|
||||||
*
|
*
|
||||||
* @param {string} action
|
* @param {string} action
|
||||||
* @param {string} title
|
* @param {TaskString} titleString
|
||||||
* @param {string} description
|
* @param {TaskString|null} descriptionString
|
||||||
* @param {boolean} showSuccess
|
* @param {boolean} showSuccess
|
||||||
* @param {Object} [data]
|
* @param {Object} [data]
|
||||||
*/
|
*/
|
||||||
setData(action, title, description, showSuccess, data = {}) {
|
setData(action, titleString, descriptionString, showSuccess, data = {}) {
|
||||||
this.id = uuidv4()
|
this.id = uuidv4()
|
||||||
this.action = action
|
this.action = action
|
||||||
this.data = { ...data }
|
this.data = { ...data }
|
||||||
this.title = title
|
this.title = titleString.text
|
||||||
this.description = description
|
this.titleKey = titleString.key || null
|
||||||
|
this.titleSubs = titleString.subs || null
|
||||||
|
this.description = descriptionString?.text || null
|
||||||
|
this.descriptionKey = descriptionString?.key || null
|
||||||
|
this.descriptionSubs = descriptionString?.subs || null
|
||||||
this.showSuccess = showSuccess
|
this.showSuccess = showSuccess
|
||||||
this.startedAt = Date.now()
|
this.startedAt = Date.now()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set task as failed
|
* Set task as failed
|
||||||
*
|
*
|
||||||
* @param {string} message error message
|
* @param {TaskString} messageString
|
||||||
*/
|
*/
|
||||||
setFailed(message) {
|
setFailed(messageString) {
|
||||||
|
this.error = messageString.text
|
||||||
|
this.errorKey = messageString.key || null
|
||||||
|
this.errorSubs = messageString.subs || null
|
||||||
|
this.isFailed = true
|
||||||
|
this.failedAt = Date.now()
|
||||||
|
this.setFinished()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set task as failed without translation key
|
||||||
|
* TODO: Remove this method after all tasks are using translation keys
|
||||||
|
*
|
||||||
|
* @param {string} message
|
||||||
|
*/
|
||||||
|
setFailedText(message) {
|
||||||
this.error = message
|
this.error = message
|
||||||
|
this.errorKey = null
|
||||||
|
this.errorSubs = null
|
||||||
this.isFailed = true
|
this.isFailed = true
|
||||||
this.failedAt = Date.now()
|
this.failedAt = Date.now()
|
||||||
this.setFinished()
|
this.setFinished()
|
||||||
@ -78,15 +121,18 @@ class Task {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set task as finished
|
* Set task as finished
|
||||||
*
|
* TODO: Update to use translation keys
|
||||||
|
*
|
||||||
* @param {string} [newDescription] update description
|
* @param {string} [newDescription] update description
|
||||||
*/
|
*/
|
||||||
setFinished(newDescription = null) {
|
setFinished(newDescription = null) {
|
||||||
if (newDescription) {
|
if (newDescription) {
|
||||||
this.description = newDescription
|
this.description = newDescription
|
||||||
|
this.descriptionKey = null
|
||||||
|
this.descriptionSubs = null
|
||||||
}
|
}
|
||||||
this.isFinished = true
|
this.isFinished = true
|
||||||
this.finishedAt = Date.now()
|
this.finishedAt = Date.now()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
module.exports = Task
|
module.exports = Task
|
||||||
|
@ -76,7 +76,12 @@ class LibraryScanner {
|
|||||||
libraryName: library.name,
|
libraryName: library.name,
|
||||||
libraryMediaType: library.mediaType
|
libraryMediaType: library.mediaType
|
||||||
}
|
}
|
||||||
const task = TaskManager.createAndAddTask('library-scan', `Scanning "${library.name}" library`, null, true, taskData)
|
const taskTitleString = {
|
||||||
|
text: `Scanning "${library.name}" library`,
|
||||||
|
key: 'MessageTaskScanningLibrary',
|
||||||
|
subs: [library.name]
|
||||||
|
}
|
||||||
|
const task = TaskManager.createAndAddTask('library-scan', taskTitleString, null, true, taskData)
|
||||||
|
|
||||||
Logger.info(`[LibraryScanner] Starting${forceRescan ? ' (forced)' : ''} library scan ${libraryScan.id} for ${libraryScan.libraryName}`)
|
Logger.info(`[LibraryScanner] Starting${forceRescan ? ' (forced)' : ''} library scan ${libraryScan.id} for ${libraryScan.libraryName}`)
|
||||||
|
|
||||||
@ -104,7 +109,7 @@ class LibraryScanner {
|
|||||||
|
|
||||||
Logger.error(`[LibraryScanner] Library scan ${libraryScan.id} failed after ${libraryScan.elapsedTimestamp} | ${libraryScan.resultStats}.`, err)
|
Logger.error(`[LibraryScanner] Library scan ${libraryScan.id} failed after ${libraryScan.elapsedTimestamp} | ${libraryScan.resultStats}.`, err)
|
||||||
|
|
||||||
task.setFailed(`Failed. ${libraryScan.scanResultsString}`)
|
task.setFailedText(`Failed. ${libraryScan.scanResultsString}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.cancelLibraryScan[libraryScan.libraryId]) delete this.cancelLibraryScan[libraryScan.libraryId]
|
if (this.cancelLibraryScan[libraryScan.libraryId]) delete this.cancelLibraryScan[libraryScan.libraryId]
|
||||||
|
@ -368,7 +368,12 @@ class Scanner {
|
|||||||
const taskData = {
|
const taskData = {
|
||||||
libraryId: library.id
|
libraryId: library.id
|
||||||
}
|
}
|
||||||
const task = TaskManager.createAndAddTask('library-match-all', `Matching books in "${library.name}"`, null, true, taskData)
|
const taskTitleString = {
|
||||||
|
text: `Matching books in "${library.name}"`,
|
||||||
|
key: 'MessageTaskMatchingBooksInLibrary',
|
||||||
|
subs: [library.name]
|
||||||
|
}
|
||||||
|
const task = TaskManager.createAndAddTask('library-match-all', taskTitleString, null, true, taskData)
|
||||||
Logger.info(`[Scanner] matchLibraryItems: Starting library match scan ${libraryScan.id} for ${libraryScan.libraryName}`)
|
Logger.info(`[Scanner] matchLibraryItems: Starting library match scan ${libraryScan.id} for ${libraryScan.libraryName}`)
|
||||||
|
|
||||||
let hasMoreChunks = true
|
let hasMoreChunks = true
|
||||||
@ -393,7 +398,7 @@ class Scanner {
|
|||||||
if (offset === 0) {
|
if (offset === 0) {
|
||||||
Logger.error(`[Scanner] matchLibraryItems: Library has no items ${library.id}`)
|
Logger.error(`[Scanner] matchLibraryItems: Library has no items ${library.id}`)
|
||||||
libraryScan.setComplete('Library has no items')
|
libraryScan.setComplete('Library has no items')
|
||||||
task.setFailed(libraryScan.error)
|
task.setFailedText(libraryScan.error)
|
||||||
} else {
|
} else {
|
||||||
libraryScan.setComplete()
|
libraryScan.setComplete()
|
||||||
task.setFinished(isCanceled ? 'Canceled' : libraryScan.scanResultsString)
|
task.setFinished(isCanceled ? 'Canceled' : libraryScan.scanResultsString)
|
||||||
|
Loading…
Reference in New Issue
Block a user