From 34ac97213016356874d189908a1f26d699146d67 Mon Sep 17 00:00:00 2001 From: mfcar Date: Mon, 27 Feb 2023 02:56:07 +0000 Subject: [PATCH] Add download queue --- client/components/app/SideRail.vue | 13 +- client/components/app/StreamContainer.vue | 20 ++- .../components/modals/podcast/EpisodeFeed.vue | 11 +- .../tables/podcast/DownloadQueueTable.vue | 68 ++++++++++ .../tables/podcast/EpisodeTableRow.vue | 9 +- .../widgets/PodcastTypeIndicator.vue | 31 +++++ .../_library/podcast/download-queue.vue | 125 ++++++++++++++++++ .../pages/library/_library/podcast/latest.vue | 11 +- client/strings/de.json | 7 +- client/strings/en-us.json | 5 + client/strings/es.json | 5 + client/strings/fr.json | 5 + client/strings/hr.json | 5 + client/strings/it.json | 5 + client/strings/pl.json | 5 + client/strings/ru.json | 5 + client/strings/zh-cn.json | 5 + server/controllers/LibraryController.js | 7 + server/managers/PodcastManager.js | 23 +++- server/objects/PodcastEpisodeDownload.js | 13 +- server/routers/ApiRouter.js | 3 +- 21 files changed, 359 insertions(+), 22 deletions(-) create mode 100644 client/components/tables/podcast/DownloadQueueTable.vue create mode 100644 client/components/widgets/PodcastTypeIndicator.vue create mode 100644 client/pages/library/_library/podcast/download-queue.vue 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 @@
+ + file_download + +

{{ $strings.ButtonDownloadQueue }}

+ +
+ + warning @@ -149,6 +157,9 @@ export default { isMusicLibrary() { return this.currentLibraryMediaType === 'music' }, + isPodcastDownloadQueuePage() { + return this.$route.name === 'library-library-podcast-download-queue' + }, isPodcastSearchPage() { return this.$route.name === 'library-library-podcast-search' }, @@ -212,4 +223,4 @@ export default { }, mounted() {} } - \ No newline at end of file + diff --git a/client/components/app/StreamContainer.vue b/client/components/app/StreamContainer.vue index 95e29554..27e79d8f 100644 --- a/client/components/app/StreamContainer.vue +++ b/client/components/app/StreamContainer.vue @@ -11,12 +11,15 @@
person -

{{ podcastAuthor }}

-

{{ musicArtists }}

-

- {{ author.name }} -

-

{{ $strings.LabelUnknown }}

+
+
{{ podcastAuthor }}
+
{{ musicArtists }}
+
+ {{ author.name }} +
+
{{ $strings.LabelUnknown }}
+ +
@@ -129,6 +132,9 @@ export default { isMusic() { return this.streamLibraryItem ? this.streamLibraryItem.mediaType === 'music' : false }, + isExplicit() { + return this.mediaMetadata.explicit || false + }, mediaMetadata() { return this.media.metadata || {} }, @@ -474,4 +480,4 @@ export default { #streamContainer { box-shadow: 0px -6px 8px #1111113f; } - \ No newline at end of file + diff --git a/client/components/modals/podcast/EpisodeFeed.vue b/client/components/modals/podcast/EpisodeFeed.vue index be701f3a..91f0b34a 100644 --- a/client/components/modals/podcast/EpisodeFeed.vue +++ b/client/components/modals/podcast/EpisodeFeed.vue @@ -19,8 +19,15 @@
-

#{{ episode.episode }}

-

{{ episode.title }}

+
+
#
+
{{ episode.season }}x
+
{{ episode.episode }}
+
+
+
{{ episode.title }}
+ +

{{ episode.subtitle }}

Published {{ episode.publishedAt ? $dateDistanceFromNow(episode.publishedAt) : 'Unknown' }}

diff --git a/client/components/tables/podcast/DownloadQueueTable.vue b/client/components/tables/podcast/DownloadQueueTable.vue new file mode 100644 index 00000000..2dfe87f0 --- /dev/null +++ b/client/components/tables/podcast/DownloadQueueTable.vue @@ -0,0 +1,68 @@ + + + diff --git a/client/components/tables/podcast/EpisodeTableRow.vue b/client/components/tables/podcast/EpisodeTableRow.vue index a184b3c8..dfb80248 100644 --- a/client/components/tables/podcast/EpisodeTableRow.vue +++ b/client/components/tables/podcast/EpisodeTableRow.vue @@ -2,9 +2,10 @@
-

- {{ title }} -

+
+ {{ title }} + +

{{ subtitle }}

@@ -205,4 +206,4 @@ export default { } } } - \ No newline at end of file + diff --git a/client/components/widgets/PodcastTypeIndicator.vue b/client/components/widgets/PodcastTypeIndicator.vue new file mode 100644 index 00000000..d914d283 --- /dev/null +++ b/client/components/widgets/PodcastTypeIndicator.vue @@ -0,0 +1,31 @@ + + + diff --git a/client/pages/library/_library/podcast/download-queue.vue b/client/pages/library/_library/podcast/download-queue.vue new file mode 100644 index 00000000..11785887 --- /dev/null +++ b/client/pages/library/_library/podcast/download-queue.vue @@ -0,0 +1,125 @@ + + diff --git a/client/pages/library/_library/podcast/latest.vue b/client/pages/library/_library/podcast/latest.vue index 344b327e..693d957a 100644 --- a/client/pages/library/_library/podcast/latest.vue +++ b/client/pages/library/_library/podcast/latest.vue @@ -30,7 +30,16 @@

{{ $dateDistanceFromNow(episode.publishedAt) }}

-

{{ episode.title }}

+
+
#
+
{{ episode.season }}x
+
{{ episode.episode }}
+
+ +
+
{{ episode.title }}
+ +

{{ episode.subtitle }}

diff --git a/client/strings/de.json b/client/strings/de.json index 57915ccd..e1c3b02f 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", @@ -493,6 +496,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", @@ -623,4 +628,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..c8e87d28 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", @@ -493,6 +496,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", diff --git a/client/strings/es.json b/client/strings/es.json index 710d5ef8..c8e87d28 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", @@ -493,6 +496,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", diff --git a/client/strings/fr.json b/client/strings/fr.json index 47f84209..2393110b 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", @@ -493,6 +496,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", diff --git a/client/strings/hr.json b/client/strings/hr.json index 36e67444..00d27566 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", @@ -493,6 +496,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", diff --git a/client/strings/it.json b/client/strings/it.json index 21bc3ae9..8818f8fd 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", @@ -493,6 +496,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", diff --git a/client/strings/pl.json b/client/strings/pl.json index c907e612..4ecdcff9 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", @@ -493,6 +496,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", diff --git a/client/strings/ru.json b/client/strings/ru.json index a1a34f70..dd50a169 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": "Найти Главы", @@ -493,6 +496,8 @@ "MessageNoCollections": "Нет Коллекций", "MessageNoCoversFound": "Обложек не найдено", "MessageNoDescription": "Нет описания", + "MessageNoDownloadsQueued": "No downloads queued", + "MessageNoDownloadsInProgress": "No downloads currently in progress", "MessageNoEpisodeMatchesFound": "Совпадения эпизодов не найдены", "MessageNoEpisodes": "Нет Эпизодов", "MessageNoFoldersAvailable": "Нет доступных папок", diff --git a/client/strings/zh-cn.json b/client/strings/zh-cn.json index 433a87bc..671fde5a 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": "查找章节", @@ -493,6 +496,8 @@ "MessageNoCollections": "没有收藏", "MessageNoCoversFound": "没有找到封面", "MessageNoDescription": "没有描述", + "MessageNoDownloadsQueued": "No downloads queued", + "MessageNoDownloadsInProgress": "No downloads currently in progress", "MessageNoEpisodeMatchesFound": "没有找到任何剧集匹配项", "MessageNoEpisodes": "没有剧集", "MessageNoFoldersAvailable": "没有可用文件夹", diff --git a/server/controllers/LibraryController.js b/server/controllers/LibraryController.js index ece93ca2..7f814591 100644 --- a/server/controllers/LibraryController.js +++ b/server/controllers/LibraryController.js @@ -82,6 +82,13 @@ class LibraryController { return res.json(req.library) } + async getDownloadQueue(req, res) { + const library = req.library + + let queue = this.podcastManager.getDownloadQueueDetails().filter(q => q.libraryId === library.id) + return res.json(queue) + } + async update(req, res) { const library = req.library diff --git a/server/managers/PodcastManager.js b/server/managers/PodcastManager.js index 74751d45..3b7e352b 100644 --- a/server/managers/PodcastManager.js +++ b/server/managers/PodcastManager.js @@ -56,12 +56,13 @@ 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('download_queue_updated', this.getDownloadQueueDetails()) if (this.currentDownload) { this.downloadQueue.push(podcastEpisodeDownload) SocketAuthority.emitter('episode_download_queued', podcastEpisodeDownload.toJSONForClient()) @@ -99,6 +100,7 @@ class PodcastManager { } SocketAuthority.emitter('episode_download_finished', this.currentDownload.toJSONForClient()) + SocketAuthority.emitter('download_queue_updated', this.getDownloadQueueDetails()) this.watcher.removeIgnoreDir(this.currentDownload.libraryItem.path) this.currentDownload = null @@ -329,5 +331,22 @@ class PodcastManager { feeds: rssFeedData } } + + getDownloadQueueDetails() { + return this.downloadQueue.map(item => { + return { + id: item.id, + libraryId: item.libraryId || null, + libraryItemId: item.libraryItemId || null, + podcastTitle: item.libraryItem.media.metadata.title || null, + podcastExplicit: item.libraryItem.media.metadata.explicit || false, + episodeDisplayTitle: item.podcastEpisode.title || null, + season: item.podcastEpisode.season || null, + episode: item.podcastEpisode.episode || null, + episodeType: item.podcastEpisode.episodeType || 'full', + publishedAt: item.podcastEpisode.publishedAt || null + } + }) + } } -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..c5ee99ab 100644 --- a/server/objects/PodcastEpisodeDownload.js +++ b/server/objects/PodcastEpisodeDownload.js @@ -8,6 +8,7 @@ class PodcastEpisodeDownload { this.podcastEpisode = null this.url = null this.libraryItem = null + this.libraryId = null this.isAutoDownload = false this.isDownloading = false @@ -25,12 +26,17 @@ class PodcastEpisodeDownload { episodeDisplayTitle: this.podcastEpisode ? this.podcastEpisode.title : null, url: this.url, libraryItemId: this.libraryItem ? this.libraryItem.id : null, + libraryId: this.libraryId || null, isDownloading: this.isDownloading, isFinished: this.isFinished, failed: this.failed, startedAt: this.startedAt, createdAt: this.createdAt, - finishedAt: this.finishedAt + finishedAt: this.finishedAt, + season: this.podcastEpisode ? this.podcastEpisode.season : null, + episode: this.podcastEpisode ? this.podcastEpisode.episode : null, + episodeType: this.podcastEpisode ? this.podcastEpisode.episodeType : 'full', + publishedAt: this.podcastEpisode ? 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..6e1837b3 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/downloads', LibraryController.middleware.bind(this), LibraryController.getDownloadQueue.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