diff --git a/client/components/app/SideRail.vue b/client/components/app/SideRail.vue index bf58e341..25350d24 100644 --- a/client/components/app/SideRail.vue +++ b/client/components/app/SideRail.vue @@ -86,6 +86,14 @@
+{{ $strings.ButtonDownloadQueue }}
+ + +{{ podcastAuthor }}
-{{ musicArtists }}
-
-
{{ $strings.LabelUnknown }}
+{{ title }}
+ +{{ description }}
+ +{{ failedMessage }}
+#{{ episode.episode }}
-{{ episode.title }}
+{{ episode.subtitle }}
Published {{ episode.publishedAt ? $dateDistanceFromNow(episode.publishedAt) : 'Unknown' }}
{{ $strings.HeaderDownloadQueue }}
+{{ $strings.LabelPodcast }} | +{{ $strings.LabelEpisode }} | +{{ $strings.LabelEpisodeTitle }} | +{{ $strings.LabelPubDate }} | +
---|---|---|---|
+
+
+ |
+
+
+
+ {{ downloadQueued.season }}x
+ {{ downloadQueued.episode }}
+ |
+ + {{ downloadQueued.episodeDisplayTitle }} + | +
+
+
+ {{ $dateDistanceFromNow(downloadQueued.publishedAt) }} + |
+
- {{ title }} -
+{{ subtitle }}
@@ -205,4 +206,4 @@ export default { } } } - \ No newline at end of file + diff --git a/client/components/widgets/NotificationWidget.vue b/client/components/widgets/NotificationWidget.vue index 6c3e82fd..f70f840d 100644 --- a/client/components/widgets/NotificationWidget.vue +++ b/client/components/widgets/NotificationWidget.vue @@ -1,15 +1,51 @@ -{{ $strings.LabelTasks }}
+ +{{ $strings.MessageNoTasksRunning }}
+{{ $strings.HeaderCurrentDownloads }}
+{{ $strings.MessageNoDownloadsInProgress }}
+ +{{ $dateDistanceFromNow(episode.publishedAt) }}
+{{ $dateDistanceFromNow(episode.publishedAt) }}
+{{ episode.subtitle }}
+{{ $dateDistanceFromNow(episode.publishedAt) }}
@@ -24,13 +26,24 @@{{ $dateDistanceFromNow(episode.publishedAt) }}
{{ episode.title }}
+{{ episode.subtitle }}
diff --git a/client/strings/de.json b/client/strings/de.json index 57915ccd..32de2cfe 100644 --- a/client/strings/de.json +++ b/client/strings/de.json @@ -20,6 +20,7 @@ "ButtonCreate": "Erstellen", "ButtonCreateBackup": "Sicherung erstellen", "ButtonDelete": "Löschen", + "ButtonDownloadQueue": "Queue", "ButtonEdit": "Bearbeiten", "ButtonEditChapters": "Kapitel bearbeiten", "ButtonEditPodcast": "Podcast bearbeiten", @@ -92,7 +93,9 @@ "HeaderCollection": "Sammlungen", "HeaderCollectionItems": "Sammlungseinträge", "HeaderCover": "Titelbild", + "HeaderCurrentDownloads": "Current Downloads", "HeaderDetails": "Details", + "HeaderDownloadQueue": "Download Queue", "HeaderEpisodes": "Episoden", "HeaderFiles": "Dateien", "HeaderFindChapters": "Kapitel suchen", @@ -392,6 +395,7 @@ "LabelTag": "Schlagwort", "LabelTags": "Schlagwörter", "LabelTagsAccessibleToUser": "Für Benutzer zugängliche Schlagwörter", + "LabelTasks": "Tasks Running", "LabelTimeListened": "Gehörte Zeit", "LabelTimeListenedToday": "Heute gehörte Zeit", "LabelTimeRemaining": "{0} verbleibend", @@ -493,6 +497,8 @@ "MessageNoCollections": "Keine Sammlungen", "MessageNoCoversFound": "Keine Titelbilder gefunden", "MessageNoDescription": "Keine Beschreibung", + "MessageNoDownloadsQueued": "No downloads queued", + "MessageNoDownloadsInProgress": "No downloads currently in progress", "MessageNoEpisodeMatchesFound": "Keine Episodenübereinstimmungen gefunden", "MessageNoEpisodes": "Keine Episoden", "MessageNoFoldersAvailable": "Keine Ordner verfügbar", @@ -509,6 +515,7 @@ "MessageNoSearchResultsFor": "Keine Suchergebnisse für \"{0}\"", "MessageNoSeries": "Keine Serien", "MessageNoTags": "Keine Tags", + "MessageNoTasksRunning": "No Tasks Running", "MessageNotYetImplemented": "Noch nicht implementiert", "MessageNoUpdateNecessary": "Keine Aktualisierung erforderlich", "MessageNoUpdatesWereNecessary": "Keine Aktualisierungen waren notwendig", @@ -623,4 +630,4 @@ "ToastSocketFailedToConnect": "Verbindung zum WebSocket fehlgeschlagen", "ToastUserDeleteFailed": "Benutzer konnte nicht gelöscht werden", "ToastUserDeleteSuccess": "Benutzer gelöscht" -} \ No newline at end of file +} diff --git a/client/strings/en-us.json b/client/strings/en-us.json index 710d5ef8..a76db534 100644 --- a/client/strings/en-us.json +++ b/client/strings/en-us.json @@ -20,6 +20,7 @@ "ButtonCreate": "Create", "ButtonCreateBackup": "Create Backup", "ButtonDelete": "Delete", + "ButtonDownloadQueue": "Queue", "ButtonEdit": "Edit", "ButtonEditChapters": "Edit Chapters", "ButtonEditPodcast": "Edit Podcast", @@ -92,7 +93,9 @@ "HeaderCollection": "Collection", "HeaderCollectionItems": "Collection Items", "HeaderCover": "Cover", + "HeaderCurrentDownloads": "Current Downloads", "HeaderDetails": "Details", + "HeaderDownloadQueue": "Download Queue", "HeaderEpisodes": "Episodes", "HeaderFiles": "Files", "HeaderFindChapters": "Find Chapters", @@ -392,6 +395,7 @@ "LabelTag": "Tag", "LabelTags": "Tags", "LabelTagsAccessibleToUser": "Tags Accessible to User", + "LabelTasks": "Tasks Running", "LabelTimeListened": "Time Listened", "LabelTimeListenedToday": "Time Listened Today", "LabelTimeRemaining": "{0} remaining", @@ -493,6 +497,8 @@ "MessageNoCollections": "No Collections", "MessageNoCoversFound": "No Covers Found", "MessageNoDescription": "No description", + "MessageNoDownloadsQueued": "No downloads queued", + "MessageNoDownloadsInProgress": "No downloads currently in progress", "MessageNoEpisodeMatchesFound": "No episode matches found", "MessageNoEpisodes": "No Episodes", "MessageNoFoldersAvailable": "No Folders Available", @@ -509,6 +515,7 @@ "MessageNoSearchResultsFor": "No search results for \"{0}\"", "MessageNoSeries": "No Series", "MessageNoTags": "No Tags", + "MessageNoTasksRunning": "No Tasks Running", "MessageNotYetImplemented": "Not yet implemented", "MessageNoUpdateNecessary": "No update necessary", "MessageNoUpdatesWereNecessary": "No updates were necessary", diff --git a/client/strings/es.json b/client/strings/es.json index 710d5ef8..a76db534 100644 --- a/client/strings/es.json +++ b/client/strings/es.json @@ -20,6 +20,7 @@ "ButtonCreate": "Create", "ButtonCreateBackup": "Create Backup", "ButtonDelete": "Delete", + "ButtonDownloadQueue": "Queue", "ButtonEdit": "Edit", "ButtonEditChapters": "Edit Chapters", "ButtonEditPodcast": "Edit Podcast", @@ -92,7 +93,9 @@ "HeaderCollection": "Collection", "HeaderCollectionItems": "Collection Items", "HeaderCover": "Cover", + "HeaderCurrentDownloads": "Current Downloads", "HeaderDetails": "Details", + "HeaderDownloadQueue": "Download Queue", "HeaderEpisodes": "Episodes", "HeaderFiles": "Files", "HeaderFindChapters": "Find Chapters", @@ -392,6 +395,7 @@ "LabelTag": "Tag", "LabelTags": "Tags", "LabelTagsAccessibleToUser": "Tags Accessible to User", + "LabelTasks": "Tasks Running", "LabelTimeListened": "Time Listened", "LabelTimeListenedToday": "Time Listened Today", "LabelTimeRemaining": "{0} remaining", @@ -493,6 +497,8 @@ "MessageNoCollections": "No Collections", "MessageNoCoversFound": "No Covers Found", "MessageNoDescription": "No description", + "MessageNoDownloadsQueued": "No downloads queued", + "MessageNoDownloadsInProgress": "No downloads currently in progress", "MessageNoEpisodeMatchesFound": "No episode matches found", "MessageNoEpisodes": "No Episodes", "MessageNoFoldersAvailable": "No Folders Available", @@ -509,6 +515,7 @@ "MessageNoSearchResultsFor": "No search results for \"{0}\"", "MessageNoSeries": "No Series", "MessageNoTags": "No Tags", + "MessageNoTasksRunning": "No Tasks Running", "MessageNotYetImplemented": "Not yet implemented", "MessageNoUpdateNecessary": "No update necessary", "MessageNoUpdatesWereNecessary": "No updates were necessary", diff --git a/client/strings/fr.json b/client/strings/fr.json index 47f84209..a4cdbfc9 100644 --- a/client/strings/fr.json +++ b/client/strings/fr.json @@ -20,6 +20,7 @@ "ButtonCreate": "Créer", "ButtonCreateBackup": "Créer une sauvegarde", "ButtonDelete": "Effacer", + "ButtonDownloadQueue": "Queue", "ButtonEdit": "Modifier", "ButtonEditChapters": "Modifier les chapitres", "ButtonEditPodcast": "Modifier les podcasts", @@ -92,7 +93,9 @@ "HeaderCollection": "Collection", "HeaderCollectionItems": "Entrées de la Collection", "HeaderCover": "Couverture", + "HeaderCurrentDownloads": "Current Downloads", "HeaderDetails": "Détails", + "HeaderDownloadQueue": "Download Queue", "HeaderEpisodes": "Épisodes", "HeaderFiles": "Fichiers", "HeaderFindChapters": "Trouver les chapitres", @@ -392,6 +395,7 @@ "LabelTag": "Étiquette", "LabelTags": "Étiquettes", "LabelTagsAccessibleToUser": "Étiquettes accessibles à l'utilisateur", + "LabelTasks": "Tasks Running", "LabelTimeListened": "Temps d'écoute", "LabelTimeListenedToday": "Nombres d'écoutes Aujourd'hui", "LabelTimeRemaining": "{0} restantes", @@ -493,6 +497,8 @@ "MessageNoCollections": "Pas de collections", "MessageNoCoversFound": "Aucune couverture trouvée", "MessageNoDescription": "Pas de description", + "MessageNoDownloadsQueued": "No downloads queued", + "MessageNoDownloadsInProgress": "No downloads currently in progress", "MessageNoEpisodeMatchesFound": "Pas de correspondance d'épisode trouvée", "MessageNoEpisodes": "Aucun épisode", "MessageNoFoldersAvailable": "Aucun dossier disponible", @@ -509,6 +515,7 @@ "MessageNoSearchResultsFor": "Pas de résultats de recherche pour \"{0}\"", "MessageNoSeries": "Pas de séries", "MessageNoTags": "Pas d'étiquettes", + "MessageNoTasksRunning": "No Tasks Running", "MessageNotYetImplemented": "Non implémenté", "MessageNoUpdateNecessary": "Pas de mise à jour nécessaire", "MessageNoUpdatesWereNecessary": "Aucune mise à jour n'était nécessaire", diff --git a/client/strings/hr.json b/client/strings/hr.json index 36e67444..404c4d78 100644 --- a/client/strings/hr.json +++ b/client/strings/hr.json @@ -20,6 +20,7 @@ "ButtonCreate": "Napravi", "ButtonCreateBackup": "Napravi backup", "ButtonDelete": "Obriši", + "ButtonDownloadQueue": "Queue", "ButtonEdit": "Edit", "ButtonEditChapters": "Uredi poglavlja", "ButtonEditPodcast": "Uredi podcast", @@ -92,7 +93,9 @@ "HeaderCollection": "Kolekcija", "HeaderCollectionItems": "Stvari u kolekciji", "HeaderCover": "Cover", + "HeaderCurrentDownloads": "Current Downloads", "HeaderDetails": "Detalji", + "HeaderDownloadQueue": "Download Queue", "HeaderEpisodes": "Epizode", "HeaderFiles": "Datoteke", "HeaderFindChapters": "Pronađi poglavlja", @@ -392,6 +395,7 @@ "LabelTag": "Tag", "LabelTags": "Tags", "LabelTagsAccessibleToUser": "Tags dostupni korisniku", + "LabelTasks": "Tasks Running", "LabelTimeListened": "Vremena odslušano", "LabelTimeListenedToday": "Vremena odslušano danas", "LabelTimeRemaining": "{0} preostalo", @@ -493,6 +497,8 @@ "MessageNoCollections": "Nema kolekcija", "MessageNoCoversFound": "Covers nisu pronađeni", "MessageNoDescription": "Nema opisa", + "MessageNoDownloadsQueued": "No downloads queued", + "MessageNoDownloadsInProgress": "No downloads currently in progress", "MessageNoEpisodeMatchesFound": "Nijedna epizoda pronađena", "MessageNoEpisodes": "Nema epizoda", "MessageNoFoldersAvailable": "Nema dostupnih foldera", @@ -509,6 +515,7 @@ "MessageNoSearchResultsFor": "Nema rezultata pretragee za \"{0}\"", "MessageNoSeries": "No Series", "MessageNoTags": "No Tags", + "MessageNoTasksRunning": "No Tasks Running", "MessageNotYetImplemented": "Not yet implemented", "MessageNoUpdateNecessary": "Aktualiziranje nije potrebno", "MessageNoUpdatesWereNecessary": "Aktualiziranje nije bilo potrebno", diff --git a/client/strings/it.json b/client/strings/it.json index 21bc3ae9..f6c2b528 100644 --- a/client/strings/it.json +++ b/client/strings/it.json @@ -20,6 +20,7 @@ "ButtonCreate": "Crea", "ButtonCreateBackup": "Crea un Backup", "ButtonDelete": "Elimina", + "ButtonDownloadQueue": "Queue", "ButtonEdit": "Edit", "ButtonEditChapters": "Modifica Capitoli", "ButtonEditPodcast": "Modifica Podcast", @@ -92,7 +93,9 @@ "HeaderCollection": "Raccolta", "HeaderCollectionItems": "Elementi della Raccolta", "HeaderCover": "Cover", + "HeaderCurrentDownloads": "Current Downloads", "HeaderDetails": "Dettagli", + "HeaderDownloadQueue": "Download Queue", "HeaderEpisodes": "Episodi", "HeaderFiles": "File", "HeaderFindChapters": "Trova Capitoli", @@ -392,6 +395,7 @@ "LabelTag": "Tag", "LabelTags": "Tags", "LabelTagsAccessibleToUser": "Tags permessi agli Utenti", + "LabelTasks": "Tasks Running", "LabelTimeListened": "Tempo di Ascolto", "LabelTimeListenedToday": "Tempo di Ascolto Oggi", "LabelTimeRemaining": "{0} rimanente", @@ -493,6 +497,8 @@ "MessageNoCollections": "Nessuna Raccolta", "MessageNoCoversFound": "Nessuna Cover Trovata", "MessageNoDescription": "Nessuna descrizione", + "MessageNoDownloadsQueued": "No downloads queued", + "MessageNoDownloadsInProgress": "No downloads currently in progress", "MessageNoEpisodeMatchesFound": "Nessun episodio corrispondente trovato", "MessageNoEpisodes": "Nessun Episodio", "MessageNoFoldersAvailable": "Nessuna Cartella disponibile", @@ -509,6 +515,7 @@ "MessageNoSearchResultsFor": "Nessun risultato per \"{0}\"", "MessageNoSeries": "Nessuna Serie", "MessageNoTags": "No Tags", + "MessageNoTasksRunning": "No Tasks Running", "MessageNotYetImplemented": "Non Ancora Implementato", "MessageNoUpdateNecessary": "Nessun aggiornamento necessario", "MessageNoUpdatesWereNecessary": "Nessun aggiornamento necessario", diff --git a/client/strings/pl.json b/client/strings/pl.json index c907e612..db18a20f 100644 --- a/client/strings/pl.json +++ b/client/strings/pl.json @@ -20,6 +20,7 @@ "ButtonCreate": "Utwórz", "ButtonCreateBackup": "Utwórz kopię zapasową", "ButtonDelete": "Usuń", + "ButtonDownloadQueue": "Queue", "ButtonEdit": "Edit", "ButtonEditChapters": "Edytuj rozdziały", "ButtonEditPodcast": "Edytuj podcast", @@ -92,7 +93,9 @@ "HeaderCollection": "Kolekcja", "HeaderCollectionItems": "Elementy kolekcji", "HeaderCover": "Okładka", + "HeaderCurrentDownloads": "Current Downloads", "HeaderDetails": "Szczegóły", + "HeaderDownloadQueue": "Download Queue", "HeaderEpisodes": "Rozdziały", "HeaderFiles": "Pliki", "HeaderFindChapters": "Wyszukaj rozdziały", @@ -392,6 +395,7 @@ "LabelTag": "Tag", "LabelTags": "Tagi", "LabelTagsAccessibleToUser": "Tagi dostępne dla użytkownika", + "LabelTasks": "Tasks Running", "LabelTimeListened": "Czas odtwarzania", "LabelTimeListenedToday": "Czas odtwarzania dzisiaj", "LabelTimeRemaining": "Pozostało {0}", @@ -493,6 +497,8 @@ "MessageNoCollections": "Brak kolekcji", "MessageNoCoversFound": "Okładki nieznalezione", "MessageNoDescription": "Brak opisu", + "MessageNoDownloadsQueued": "No downloads queued", + "MessageNoDownloadsInProgress": "No downloads currently in progress", "MessageNoEpisodeMatchesFound": "Nie znaleziono pasujących odcinków", "MessageNoEpisodes": "Brak odcinków", "MessageNoFoldersAvailable": "Brak dostępnych folderów", @@ -509,6 +515,7 @@ "MessageNoSearchResultsFor": "Brak wyników wyszukiwania dla \"{0}\"", "MessageNoSeries": "No Series", "MessageNoTags": "No Tags", + "MessageNoTasksRunning": "No Tasks Running", "MessageNotYetImplemented": "Jeszcze nie zaimplementowane", "MessageNoUpdateNecessary": "Brak konieczności aktualizacji", "MessageNoUpdatesWereNecessary": "Brak aktualizacji", diff --git a/client/strings/ru.json b/client/strings/ru.json index a1a34f70..dd5d36d2 100644 --- a/client/strings/ru.json +++ b/client/strings/ru.json @@ -20,6 +20,7 @@ "ButtonCreate": "Создать", "ButtonCreateBackup": "Создать бэкап", "ButtonDelete": "Удалить", + "ButtonDownloadQueue": "Queue", "ButtonEdit": "Редактировать", "ButtonEditChapters": "Редактировать Главы", "ButtonEditPodcast": "Редактировать Подкаст", @@ -92,7 +93,9 @@ "HeaderCollection": "Коллекция", "HeaderCollectionItems": "Элементы Коллекции", "HeaderCover": "Обложка", + "HeaderCurrentDownloads": "Current Downloads", "HeaderDetails": "Подробности", + "HeaderDownloadQueue": "Download Queue", "HeaderEpisodes": "Эпизоды", "HeaderFiles": "Файлы", "HeaderFindChapters": "Найти Главы", @@ -392,6 +395,7 @@ "LabelTag": "Тег", "LabelTags": "Теги", "LabelTagsAccessibleToUser": "Теги Доступные для Пользователя", + "LabelTasks": "Tasks Running", "LabelTimeListened": "Время Прослушивания", "LabelTimeListenedToday": "Время Прослушивания Сегодня", "LabelTimeRemaining": "{0} осталось", @@ -493,6 +497,8 @@ "MessageNoCollections": "Нет Коллекций", "MessageNoCoversFound": "Обложек не найдено", "MessageNoDescription": "Нет описания", + "MessageNoDownloadsQueued": "No downloads queued", + "MessageNoDownloadsInProgress": "No downloads currently in progress", "MessageNoEpisodeMatchesFound": "Совпадения эпизодов не найдены", "MessageNoEpisodes": "Нет Эпизодов", "MessageNoFoldersAvailable": "Нет доступных папок", @@ -509,6 +515,7 @@ "MessageNoSearchResultsFor": "Нет результатов поиска для \"{0}\"", "MessageNoSeries": "Нет Серий", "MessageNoTags": "Нет Тегов", + "MessageNoTasksRunning": "No Tasks Running", "MessageNotYetImplemented": "Пока не реализовано", "MessageNoUpdateNecessary": "Обновление не требуется", "MessageNoUpdatesWereNecessary": "Обновления не требовались", diff --git a/client/strings/zh-cn.json b/client/strings/zh-cn.json index 433a87bc..16234d90 100644 --- a/client/strings/zh-cn.json +++ b/client/strings/zh-cn.json @@ -20,6 +20,7 @@ "ButtonCreate": "创建", "ButtonCreateBackup": "创建备份", "ButtonDelete": "删除", + "ButtonDownloadQueue": "Queue", "ButtonEdit": "编辑", "ButtonEditChapters": "编辑章节", "ButtonEditPodcast": "编辑播客", @@ -92,7 +93,9 @@ "HeaderCollection": "收藏", "HeaderCollectionItems": "收藏项目", "HeaderCover": "封面", + "HeaderCurrentDownloads": "Current Downloads", "HeaderDetails": "详情", + "HeaderDownloadQueue": "Download Queue", "HeaderEpisodes": "剧集", "HeaderFiles": "文件", "HeaderFindChapters": "查找章节", @@ -392,6 +395,7 @@ "LabelTag": "标签", "LabelTags": "标签", "LabelTagsAccessibleToUser": "用户可访问的标签", + "LabelTasks": "Tasks Running", "LabelTimeListened": "收听时间", "LabelTimeListenedToday": "今日收听的时间", "LabelTimeRemaining": "剩余 {0}", @@ -493,6 +497,8 @@ "MessageNoCollections": "没有收藏", "MessageNoCoversFound": "没有找到封面", "MessageNoDescription": "没有描述", + "MessageNoDownloadsQueued": "No downloads queued", + "MessageNoDownloadsInProgress": "No downloads currently in progress", "MessageNoEpisodeMatchesFound": "没有找到任何剧集匹配项", "MessageNoEpisodes": "没有剧集", "MessageNoFoldersAvailable": "没有可用文件夹", @@ -509,6 +515,7 @@ "MessageNoSearchResultsFor": "没有搜索到结果 \"{0}\"", "MessageNoSeries": "无系列", "MessageNoTags": "无标签", + "MessageNoTasksRunning": "No Tasks Running", "MessageNotYetImplemented": "尚未实施", "MessageNoUpdateNecessary": "无需更新", "MessageNoUpdatesWereNecessary": "无需更新", diff --git a/server/Server.js b/server/Server.js index a5a0b8b5..4a900a68 100644 --- a/server/Server.js +++ b/server/Server.js @@ -72,7 +72,7 @@ class Server { this.abMergeManager = new AbMergeManager(this.db, this.taskManager) this.playbackSessionManager = new PlaybackSessionManager(this.db) this.coverManager = new CoverManager(this.db, this.cacheManager) - this.podcastManager = new PodcastManager(this.db, this.watcher, this.notificationManager) + this.podcastManager = new PodcastManager(this.db, this.watcher, this.notificationManager, this.taskManager) this.audioMetadataManager = new AudioMetadataMangaer(this.db, this.taskManager) this.rssFeedManager = new RssFeedManager(this.db) this.eBookManager = new EBookManager(this.db) diff --git a/server/controllers/LibraryController.js b/server/controllers/LibraryController.js index ece93ca2..ac6405fb 100644 --- a/server/controllers/LibraryController.js +++ b/server/controllers/LibraryController.js @@ -82,6 +82,11 @@ class LibraryController { return res.json(req.library) } + async getEpisodeDownloadQueue(req, res) { + const libraryDownloadQueueDetails = this.podcastManager.getDownloadQueueDetails(req.library.id) + return res.json(libraryDownloadQueueDetails) + } + async update(req, res) { const library = req.library diff --git a/server/controllers/LibraryItemController.js b/server/controllers/LibraryItemController.js index 553095d6..05aee92d 100644 --- a/server/controllers/LibraryItemController.js +++ b/server/controllers/LibraryItemController.js @@ -36,8 +36,11 @@ class LibraryItemController { }).filter(au => au) } } else if (includeEntities.includes('downloads')) { - var downloadsInQueue = this.podcastManager.getEpisodeDownloadsInQueue(req.libraryItem.id) - item.episodesDownloading = downloadsInQueue.map(d => d.toJSONForClient()) + const downloadsInQueue = this.podcastManager.getEpisodeDownloadsInQueue(req.libraryItem.id) + item.episodeDownloadsQueued = downloadsInQueue.map(d => d.toJSONForClient()) + if (this.podcastManager.currentDownload?.libraryItemId === req.libraryItem.id) { + item.episodesDownloading = [this.podcastManager.currentDownload.toJSONForClient()] + } } return res.json(item) diff --git a/server/managers/PodcastManager.js b/server/managers/PodcastManager.js index 74751d45..593d9754 100644 --- a/server/managers/PodcastManager.js +++ b/server/managers/PodcastManager.js @@ -14,12 +14,14 @@ const LibraryFile = require('../objects/files/LibraryFile') const PodcastEpisodeDownload = require('../objects/PodcastEpisodeDownload') const PodcastEpisode = require('../objects/entities/PodcastEpisode') const AudioFile = require('../objects/files/AudioFile') +const Task = require("../objects/Task") class PodcastManager { - constructor(db, watcher, notificationManager) { + constructor(db, watcher, notificationManager, taskManager) { this.db = db this.watcher = watcher this.notificationManager = notificationManager + this.taskManager = taskManager this.downloadQueue = [] this.currentDownload = null @@ -56,18 +58,28 @@ class PodcastManager { newPe.setData(ep, index++) newPe.libraryItemId = libraryItem.id var newPeDl = new PodcastEpisodeDownload() - newPeDl.setData(newPe, libraryItem, isAutoDownload) + newPeDl.setData(newPe, libraryItem, isAutoDownload, libraryItem.libraryId) this.startPodcastEpisodeDownload(newPeDl) }) } async startPodcastEpisodeDownload(podcastEpisodeDownload) { + SocketAuthority.emitter('episode_download_queue_updated', this.getDownloadQueueDetails()) if (this.currentDownload) { this.downloadQueue.push(podcastEpisodeDownload) SocketAuthority.emitter('episode_download_queued', podcastEpisodeDownload.toJSONForClient()) return } + const task = new Task() + const taskDescription = `Downloading episode "${podcastEpisodeDownload.podcastEpisode.title}".` + const taskData = { + libraryId: podcastEpisodeDownload.libraryId, + libraryItemId: podcastEpisodeDownload.libraryItemId, + } + task.setData('download-podcast-episode', 'Downloading Episode', taskDescription, taskData) + this.taskManager.addTask(task) + SocketAuthority.emitter('episode_download_started', podcastEpisodeDownload.toJSONForClient()) this.currentDownload = podcastEpisodeDownload @@ -81,7 +93,7 @@ class PodcastManager { await filePerms.setDefault(this.currentDownload.libraryItem.path) } - var success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath).then(() => true).catch((error) => { + let success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath).then(() => true).catch((error) => { Logger.error(`[PodcastManager] Podcast Episode download failed`, error) return false }) @@ -90,15 +102,21 @@ class PodcastManager { if (!success) { await fs.remove(this.currentDownload.targetPath) this.currentDownload.setFinished(false) + task.setFailed('Failed to download episode') } else { Logger.info(`[PodcastManager] Successfully downloaded podcast episode "${this.currentDownload.podcastEpisode.title}"`) this.currentDownload.setFinished(true) + task.setFinished() } } else { + task.setFailed('Failed to download episode') this.currentDownload.setFinished(false) } + this.taskManager.taskFinished(task) + SocketAuthority.emitter('episode_download_finished', this.currentDownload.toJSONForClient()) + SocketAuthority.emitter('episode_download_queue_updated', this.getDownloadQueueDetails()) this.watcher.removeIgnoreDir(this.currentDownload.libraryItem.path) this.currentDownload = null @@ -329,5 +347,15 @@ class PodcastManager { feeds: rssFeedData } } + + getDownloadQueueDetails(libraryId = null) { + let _currentDownload = this.currentDownload + if (libraryId && _currentDownload?.libraryId !== libraryId) _currentDownload = null + + return { + currentDownload: _currentDownload?.toJSONForClient(), + queue: this.downloadQueue.filter(item => !libraryId || item.libraryId === libraryId).map(item => item.toJSONForClient()) + } + } } -module.exports = PodcastManager \ No newline at end of file +module.exports = PodcastManager diff --git a/server/objects/PodcastEpisodeDownload.js b/server/objects/PodcastEpisodeDownload.js index 38a371e5..73eee038 100644 --- a/server/objects/PodcastEpisodeDownload.js +++ b/server/objects/PodcastEpisodeDownload.js @@ -8,9 +8,9 @@ class PodcastEpisodeDownload { this.podcastEpisode = null this.url = null this.libraryItem = null + this.libraryId = null this.isAutoDownload = false - this.isDownloading = false this.isFinished = false this.failed = false @@ -22,15 +22,21 @@ class PodcastEpisodeDownload { toJSONForClient() { return { id: this.id, - episodeDisplayTitle: this.podcastEpisode ? this.podcastEpisode.title : null, + episodeDisplayTitle: this.podcastEpisode?.title ?? null, url: this.url, - libraryItemId: this.libraryItem ? this.libraryItem.id : null, - isDownloading: this.isDownloading, + libraryItemId: this.libraryItem?.id || null, + libraryId: this.libraryId || null, isFinished: this.isFinished, failed: this.failed, startedAt: this.startedAt, createdAt: this.createdAt, - finishedAt: this.finishedAt + finishedAt: this.finishedAt, + podcastTitle: this.libraryItem?.media.metadata.title ?? null, + podcastExplicit: !!this.libraryItem?.media.metadata.explicit, + season: this.podcastEpisode?.season ?? null, + episode: this.podcastEpisode?.episode ?? null, + episodeType: this.podcastEpisode?.episodeType ?? 'full', + publishedAt: this.podcastEpisode?.publishedAt ?? null } } @@ -47,13 +53,14 @@ class PodcastEpisodeDownload { return this.libraryItem ? this.libraryItem.id : null } - setData(podcastEpisode, libraryItem, isAutoDownload) { + setData(podcastEpisode, libraryItem, isAutoDownload, libraryId) { this.id = getId('epdl') this.podcastEpisode = podcastEpisode this.url = encodeURI(podcastEpisode.enclosure.url) this.libraryItem = libraryItem this.isAutoDownload = isAutoDownload this.createdAt = Date.now() + this.libraryId = libraryId } setFinished(success) { @@ -62,4 +69,4 @@ class PodcastEpisodeDownload { this.failed = !success } } -module.exports = PodcastEpisodeDownload \ No newline at end of file +module.exports = PodcastEpisodeDownload diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js index 41c26769..454eb1a3 100644 --- a/server/routers/ApiRouter.js +++ b/server/routers/ApiRouter.js @@ -76,6 +76,7 @@ class ApiRouter { this.router.get('/libraries/:id/items', LibraryController.middleware.bind(this), LibraryController.getLibraryItems.bind(this)) this.router.delete('/libraries/:id/issues', LibraryController.middleware.bind(this), LibraryController.removeLibraryItemsWithIssues.bind(this)) + this.router.get('/libraries/:id/episode-downloads', LibraryController.middleware.bind(this), LibraryController.getEpisodeDownloadQueue.bind(this)) this.router.get('/libraries/:id/series', LibraryController.middleware.bind(this), LibraryController.getAllSeriesForLibrary.bind(this)) this.router.get('/libraries/:id/collections', LibraryController.middleware.bind(this), LibraryController.getCollectionsForLibrary.bind(this)) this.router.get('/libraries/:id/playlists', LibraryController.middleware.bind(this), LibraryController.getUserPlaylistsForLibrary.bind(this)) @@ -553,4 +554,4 @@ class ApiRouter { } } } -module.exports = ApiRouter \ No newline at end of file +module.exports = ApiRouter