diff --git a/build/debian/DEBIAN/preinst b/build/debian/DEBIAN/preinst index 241a47010..e30bc490c 100644 --- a/build/debian/DEBIAN/preinst +++ b/build/debian/DEBIAN/preinst @@ -22,7 +22,7 @@ add_user() { declare -r descr="${4:-No description}" declare -r shell="${5:-/bin/false}" - if ! getent passwd "$user" 2>&1 >/dev/null; then + if ! getent passwd | grep -q "^$user:"; then echo "Creating system user: $user in $group with $descr and shell $shell" useradd $uid_flags --gid $group --no-create-home --system --shell $shell -c "$descr" $user fi @@ -39,7 +39,7 @@ add_group() { declare -r gid_flags="--gid $gid" fi - if ! getent group "$group" 2>&1 >/dev/null; then + if ! getent group | grep -q "^$group:" ; then echo "Creating system group: $group" groupadd $gid_flags --system $group fi diff --git a/client/components/modals/playlists/AddCreateModal.vue b/client/components/modals/playlists/AddCreateModal.vue index f8543f1de..e695ccb0c 100644 --- a/client/components/modals/playlists/AddCreateModal.vue +++ b/client/components/modals/playlists/AddCreateModal.vue @@ -97,10 +97,7 @@ export default { ...playlist } }) - .sort((a, b) => { - if (a.isItemIncluded !== b.isItemIncluded) return a.isItemIncluded ? -1 : 1 - return a.name.localeCompare(b.name) - }) + .sort((a, b) => (a.isItemIncluded ? -1 : 1)) }, isBatch() { return this.selectedPlaylistItems.length > 1 diff --git a/client/components/ui/MultiSelect.vue b/client/components/ui/MultiSelect.vue index 3dcfb0495..c7572ba50 100644 --- a/client/components/ui/MultiSelect.vue +++ b/client/components/ui/MultiSelect.vue @@ -278,7 +278,7 @@ export default { }) }, insertNewItem(item) { - if (!this.selected.includes(item)) this.selected.push(item) + this.selected.push(item) this.$emit('input', this.selected) this.$emit('newItem', item) this.textInput = null diff --git a/client/components/ui/MultiSelectQueryInput.vue b/client/components/ui/MultiSelectQueryInput.vue index 4bc434cbd..18abc66e7 100644 --- a/client/components/ui/MultiSelectQueryInput.vue +++ b/client/components/ui/MultiSelectQueryInput.vue @@ -287,7 +287,7 @@ export default { }) }, insertNewItem(item) { - if (!this.selected.find((i) => i.name === item.name)) this.selected.push(item) + this.selected.push(item) this.$emit('input', this.selected) this.$emit('newItem', item) this.textInput = null diff --git a/client/package-lock.json b/client/package-lock.json index 568274c80..2d41d39ef 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,12 +1,12 @@ { "name": "audiobookshelf-client", - "version": "2.32.0", + "version": "2.31.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "audiobookshelf-client", - "version": "2.32.0", + "version": "2.31.0", "license": "ISC", "dependencies": { "@nuxtjs/axios": "^5.13.6", diff --git a/client/package.json b/client/package.json index df71f6256..33d66c276 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "audiobookshelf-client", - "version": "2.32.0", + "version": "2.31.0", "buildNumber": 1, "description": "Self-hosted audiobook and podcast client", "main": "index.js", diff --git a/client/strings/el.json b/client/strings/el.json index 881bd971b..9d12d3096 100644 --- a/client/strings/el.json +++ b/client/strings/el.json @@ -49,7 +49,6 @@ "ButtonMapChapterTitles": "Χαρτογράφηση Τίτλων Κεφαλαίων", "ButtonMatchAllAuthors": "Αντιστοίχιση Όλων των Συγγραφέων", "ButtonMatchBooks": "Αντιστοίχιση Βιβλίων", - "ButtonNevermind": "Άστο", "ButtonNext": "Επόμενο", "ButtonNextChapter": "Επόμενο Κεφάλαιο", "ButtonNextItemInQueue": "Επόμενο Αντικείμενο στην Ουρά", @@ -63,13 +62,8 @@ "ButtonPlaylists": "Λίστες Αναπαραγωγής", "ButtonPrevious": "Προηγούμενο", "ButtonPreviousChapter": "Προηγούμενο Κεφάλαιο", - "ButtonProbeAudioFile": "Ανάλυση Αρχείου Ήχου", - "ButtonPurgeAllCache": "Εκκαθάριση Όλης της Προσωρινής Μνήμης", - "ButtonPurgeItemsCache": "Εκκαθάριση της Μνήμης Αντικειμένων", "ButtonQueueAddItem": "Προσθήκη στην ουρά", "ButtonQueueRemoveItem": "Αφαίρεση απ'την ουρά", - "ButtonQuickEmbed": "Γρήγορη Ενσωμάτωση", - "ButtonQuickEmbedMetadata": "Γρήγορη Ενσωμάτωση Μεταδεδομένων", "ButtonQuickMatch": "Γρήγορη Αντιστοίχηση", "ButtonReScan": "Επανασάρωση", "ButtonRead": "Ανάγνωση", @@ -79,237 +73,35 @@ "ButtonRemove": "Αφαίρεση", "ButtonRemoveAll": "Αφαίρεση Όλων", "ButtonRemoveAllLibraryItems": "Αφαίρεση Όλων των Αντικειμέων Βιβλιοθήκης", - "ButtonRemoveFromContinueListening": "Αφαίρεση από τη Συνέχεια Ακρόασης", - "ButtonRemoveFromContinueReading": "Αφαίρεση από τη Συνέχεια Ανάγνωσης", - "ButtonRemoveSeriesFromContinueSeries": "Αφαίρεση Σειράς από τη Συνέχεια Σειράς", "ButtonReset": "Επαναφορά", "ButtonResetToDefault": "Επαναφορά στις προεπιλογές", "ButtonRestore": "Επαναφορά", "ButtonSave": "Αποθήκευση", "ButtonSaveAndClose": "Αποθήκευση και Κλείσιμο", - "ButtonSaveTracklist": "Αποθήκευση Λίστας Κομματιών", "ButtonScan": "Σάρψση", - "ButtonScanLibrary": "Σάρωση Βιβλιοθήκης", - "ButtonScrollLeft": "Κύλιση Αριστερά", - "ButtonScrollRight": "Κύλιση Δεξιά", "ButtonSearch": "Αναζήτηση", - "ButtonSelectFolderPath": "Επιλογή Διαδρομής Φακέλου", "ButtonSeries": "Σειρά", - "ButtonSetChaptersFromTracks": "Ορισμός κεφαλαίων από τα κομμάτια", - "ButtonShare": "Κοινοποίηση", - "ButtonShiftTimes": "Χρόνοι Μετακίνησης", - "ButtonShow": "Εμφάνιση", - "ButtonStartM4BEncode": "Έναρξη Κωδικοποίησης M4B", - "ButtonStats": "Στατιστικά", "ButtonSubmit": "Υποβολή", - "ButtonTest": "Δοκιμή", - "ButtonUpload": "Μεταφόρτωση", - "ButtonUploadBackup": "Μεταφόρτωση Αντιγράφου Ασφαλείας", - "ButtonUploadCover": "Μεταφόρτωση Εξωφύλλου", - "ButtonUploadOPMLFile": "Μεταφόρτωση Αρχείου OPML", - "ButtonUserDelete": "Διαγραφή Χρήστη {0}", - "ButtonUserEdit": "Επεξεργασίας χρήστη {0}", - "ButtonViewAll": "Εμφάνιση Όλων", "ButtonYes": "Ναι", - "ErrorUploadLacksTitle": "Πρέπει να έχει τίτλο", "HeaderAccount": "Λογαριασμός", "HeaderAdvanced": "Για Προχωρημένους", - "HeaderApiKeys": "Κλειδιά API", "HeaderAudioTracks": "Κομμάτια Ήχου", - "HeaderBackups": "Αντίγραφα Ασφαλείας", - "HeaderBulkChapterModal": "Προσθήκη Πολλαπλών Κεφαλαίων", - "HeaderChangePassword": "Αλλαγή Κωδικού Πρόσβασης", "HeaderChapters": "Κεφάλαια", - "HeaderChooseAFolder": "Επιλογή Φακέλου", "HeaderCollection": "Συλλογή", "HeaderCollectionItems": "Αντικείμενα Συλλογής", - "HeaderCover": "Εξώφυλλο", - "HeaderCurrentDownloads": "Τρέχουσες Λήψεις", "HeaderDetails": "Λεπτομέρειες", - "HeaderDownloadQueue": "Ουρά Λήψης", "HeaderEbookFiles": "Αρχεία Ebook", - "HeaderEmail": "Ηλεκτρονικό Ταχυδρομίο", - "HeaderEmailSettings": "Ρυθμίσεις Ηλεκτρονικού Ταχυδρομίου", "HeaderEpisodes": "Επεισόδια", "HeaderEreaderSettings": "Ρυθμίσεις Ereader", - "HeaderFiles": "Αρχεία", - "HeaderFindChapters": "Εύρεση Κεφαλαίων", - "HeaderItemFiles": "Αρχεία Αντικειμένων", - "HeaderLastListeningSession": "Τελευταία Συνεδρία Ακρόασης", "HeaderLatestEpisodes": "Τελευταία Επεισόδια", "HeaderLibraries": "Βιβλιοθήκες", - "HeaderLibraryFiles": "Αρχεία Βιβλιοθήκης", - "HeaderLibraryStats": "Στατιστικά Βιβλιοθήκης", - "HeaderListeningSessions": "Συνεδρίες Ακρόασης", - "HeaderListeningStats": "Στατιστικά Ακρόασης", - "HeaderMatch": "Ταύτιση", - "HeaderNewAccount": "Νέος Λογαριασμός", - "HeaderNewApiKey": "Νέο Κλειδί API", - "HeaderNewLibrary": "Νέα Βιβλιοθήκη", - "HeaderNotificationCreate": "Δημιουργία Ειδοποίησης", - "HeaderNotificationUpdate": "Ενημέρωση Ειδοποίησης", - "HeaderNotifications": "Ειδοποιήσεις", "HeaderOpenRSSFeed": "Άνοιγμα Τροφοδοσίας RSS", - "HeaderOtherFiles": "Άλλα Αρχεία", - "HeaderPermissions": "Δικαιώματα", - "HeaderPlayerSettings": "Ρυθμίσεις Αναπαραγωγής", "HeaderPlaylist": "Λίστα Αναπαραγωγής", "HeaderPlaylistItems": "Αντικείμενα Λίστας Αναπαραγωγής", - "HeaderPresets": "Προεπιλογές", "HeaderRSSFeedGeneral": "Λεπτομέρειες RSS", "HeaderRSSFeedIsOpen": "Η Τροφοδοσία RSS είναι Ανοιχτή", - "HeaderRemoveEpisode": "Αφαίρεση Επεισοδίου", - "HeaderSession": "Συνεδρία", - "HeaderSetBackupSchedule": "Ορισμός Προγράμματος Αντιγράφων Ασφαλείας", "HeaderSettings": "Ρυθμίσεις", - "HeaderSettingsDisplay": "Προβολή", - "HeaderSettingsGeneral": "Γενικά", - "HeaderSettingsSecurity": "Ασφάλεια", - "HeaderSleepTimer": "Χρονοδιακόπτης Ύπνου", - "HeaderStatsLargestItems": "Μεγαλύτερα Αντικείμενα", - "HeaderStatsLongestItems": "Μεγαλύτερα Αντικείμενα (ώρες)", "HeaderStatsMinutesListeningChart": "Λεπτά Ακρόασης (τελευταίες 7 ημέρες)", "HeaderStatsRecentSessions": "Πρόσφατες Συνεδρίες", - "HeaderStatsTop10Authors": "10 Κορυφαίου Συγγραφείς", - "HeaderStatsTop5Genres": "5 Κορυφαία Είδη", - "HeaderTableOfContents": "Πίνακας Περιεχομένων", - "HeaderTools": "Εργαλεία", - "HeaderUpdateAccount": "Ενημέρωση Λογαριασμού", - "HeaderUpdateApiKey": "Ενημέρωση Κλειδιού API", - "HeaderUpdateAuthor": "Ενημέρωση Συγγραφέα", - "HeaderUpdateDetails": "Ενημέρωση Λεπτομερειεών", - "HeaderUpdateLibrary": "Ενημέρωση Βιβλιοθήκης", - "HeaderUsers": "Χρήστες", - "HeaderYourStats": "Τα Στατιστικά Σας", - "LabelAbridged": "Συνοπτικό", - "LabelAccessibleBy": "Προσβάσιμο από", - "LabelAccountType": "Τύπος Λογαριασμού", - "LabelAccountTypeAdmin": "Διαχειριστής", - "LabelAccountTypeGuest": "Επισκέπτης", - "LabelAccountTypeUser": "Χρήστης", - "LabelAddToCollection": "Προσθήκη σε Συλλογή", - "LabelAddToCollectionBatch": "Προσθήκη {0} Βιβλίων στην Συλλογή", - "LabelAddToPlaylist": "Προσθήκη στην Λίστα Αναπαραγωγής", - "LabelAddedAt": "Προστέθηκε Στις", - "LabelAddedDate": "Προστέθηκε {0}", - "LabelAll": "Όλα", - "LabelAllEpisodesDownloaded": "Όλα τα επεισόδια λήφθηκαν", - "LabelAllUsers": "Όλοι οι Χρήστες", - "LabelAlreadyInYourLibrary": "Υπάρχει ήδη στην βιβλιοθήκη", - "LabelAudioChannels": "Κανάλια Ήχου (1 ή 2)", - "LabelAuthor": "Συγγραφέας", - "LabelAuthorFirstLast": "Συγγραφέας (Όνομα Επώνυμο)", - "LabelAuthorLastFirst": "Συγγραφέας (Επώνυμο, Όνομα)", - "LabelAuthors": "Συγγραφείς", - "LabelAutoDownloadEpisodes": "Αυτόματο Κατέβασμα Επεισοδίων", - "LabelAutoLaunch": "Αυτόματη Εκκίνηση", - "LabelBackupLocation": "Τοποθεσία Αντιγράφου Ασφαλείας", - "LabelBackupsEnableAutomaticBackups": "Αυτόματα αντίγραφα ασφαλείας", - "LabelBackupsNumberToKeep": "Αριθμός αντιγράφων ασφαλείας προς διατήρηση", - "LabelBooks": "Βιβλία", - "LabelButtonText": "Κείμενο Κουμπιού", - "LabelByAuthor": "κατά {0}", - "LabelChangePassword": "Αλλαγή Κωδικού Πρόσβασης", - "LabelChannels": "Κανάλια", - "LabelChapterCount": "{0} Κεφάλαια", - "LabelChapterTitle": "Τίτλος Κεφαλαίου", - "LabelChapters": "Κεφάλαια", - "LabelChaptersFound": "κεφάλαια βρέθηκαν", - "LabelClosePlayer": "Κλείσιμο αναπαραγωγής", - "LabelCollection": "Συλλογή", - "LabelCollections": "Συλλογές", - "LabelComplete": "Ολοκλήρωση", - "LabelConfirmPassword": "Επιβεβαίωση Κωδικού Πρόσβασης", - "LabelContinueListening": "Συνέχεια Ακρόασης", - "LabelContinueReading": "Συνέχεια Ανάγνωσης", - "LabelContinueSeries": "Συνέχεια Σειράς", - "LabelCover": "Εξώφυλλο", - "LabelCoverImageURL": "URL Εικόνας Εξωφύλλου", - "LabelCoverProvider": "Πάροχος Εξωφύλλου", - "LabelCreatedAt": "Δημιουρήθηκε Στις", - "LabelCurrent": "Τρέχων", - "LabelCurrently": "Τρέχων:", - "LabelDays": "Ημέρες", - "LabelDescription": "Περιγραφή", - "LabelDevice": "Συσκευή", - "LabelDeviceInfo": "Πληροφορίες Συσκευής", - "LabelDownload": "Λήψη", - "LabelDownloadNEpisodes": "Λήψη {0} επεισοδίων", - "LabelDuration": "Διάρκεια", - "LabelDurationComparisonExactMatch": "(ακριβής ταύτιση)", - "LabelEbook": "Ebook", - "LabelEbooks": "Ebooks", - "LabelEdit": "Επεξεργασία", - "LabelEmail": "Ηλεκτρονικό Ταχυδρομίο", - "LabelEmailSettingsFromAddress": "Από Διεύθυνση", - "LabelEmailSettingsSecure": "Ασφαλές", - "LabelEmailSettingsTestAddress": "Δοκιμή Διεύθυνσης", - "LabelEmbeddedCover": "Ενσωματωμένο Εξώφυλλο", - "LabelEnable": "Ενεργοποίηση", - "LabelEnd": "Τέλος", - "LabelEndOfChapter": "Τέλος Κεφαλαίου", - "LabelEpisode": "Επεισόδιο", - "LabelFile": "Αρχείο", - "LabelFilename": "Όνομα Αρχείου", - "LabelFinished": "Ολοκληρώθηκε", - "LabelFolder": "Φάκελος", - "LabelFontFamily": "Οικογένεια Γραμματοσειράς", - "LabelGenre": "Είδος", - "LabelGenres": "Είδη", - "LabelHost": "Διακομιστής", - "LabelInProgress": "Σε Εξέλιξη", - "LabelLanguage": "Γλώσσα", - "LabelLayoutSinglePage": "Μονή Σελίδα", - "LabelListenAgain": "Επανάληψη Ακρόασης", - "LabelMediaType": "Τύπος Πολυμέσων", - "LabelMore": "Περισσότερα", - "LabelMoreInfo": "Περισσότερες Πληροφορίες", - "LabelName": "Όνομα", - "LabelNarrator": "Αφηγητής", - "LabelNarrators": "Αφηγητές", - "LabelNewestAuthors": "Πρόσφατοι Συγγραφείς", - "LabelNewestEpisodes": "Πρόσφατα Επεισόδια", - "LabelNotStarted": "Δεν Έχει Ξεκινήσει", - "LabelNumberOfEpisodes": "# Επεισοδίων", - "LabelPassword": "Κωδικός Πρόσβασης", - "LabelPath": "Διαδρομή", - "LabelProgress": "Πρόοδος", - "LabelPublishYear": "Χρονολογία Έκδοσης", - "LabelPublishedDate": "Εκδόθηκε {0}", - "LabelRandomly": "Τυχαία", - "LabelRead": "Ανάγνωση", - "LabelReadAgain": "Ανάγνωση Ξανά", - "LabelRecentSeries": "Πρόσφατη Σειρά", - "LabelRecentlyAdded": "Προστέθηκαν Πρόσφατα", - "LabelSeries": "Σειρά", - "LabelSetEbookAsPrimary": "Ορισμός ως πρωτεύων", - "LabelShowAll": "Εμφάνιση Όλων", - "LabelSize": "Μέγεθος", - "LabelSleepTimer": "Χρονοδιακόπτης Ύπνου", - "LabelStart": "Έναρξη", - "LabelStatsBestDay": "Καλύτερη Ημέρα", - "LabelStatsDailyAverage": "Ημερήσιος Μέσος Όρος", - "LabelStatsDays": "Ημέρες", - "LabelStatsDaysListened": "Ημέρες Ακρόασης", - "LabelStatsInARow": "Σε σειρά", - "LabelStatsItemsFinished": "Ολοκληρωμένα Αντικείμενα", - "LabelStatsMinutes": "λεπτά", - "LabelStatsMinutesListening": "Λεπτά Ακρόασης", - "LabelStatsWeekListening": "Εβδομαδιαία Ακρόαση", - "LabelTheme": "Θέμα", - "LabelThemeDark": "Σκοτεινό", - "LabelThemeLight": "Φωτεινό", - "LabelTimeRemaining": "{0} απομένουν", - "LabelTitle": "Τίτλος", - "LabelTracks": "Κομμάτια", - "LabelType": "Τύπος", - "LabelUnknown": "Άγνωστο", - "LabelUser": "Χρήστης", - "LabelUsername": "Όνομα Χρήστη", - "LabelYourProgress": "Η Πρόοδος Σας", - "MessageDownloadingEpisode": "Λήψη επεισοδίου", - "MessageLoading": "Φόρτωση...", - "MessageMarkAsFinished": "Σήμανση ως Ολοκληρωμένο", - "MessageNoItemsFound": "Δεν βρέθηκαν αντικείμενα", - "MessageNoUserPlaylists": "Δεν έχετε λίστες αναπαραγωγής" + "HeaderTableOfContents": "Πίνακας Περιεχομένων" } diff --git a/client/strings/pl.json b/client/strings/pl.json index 32c9766ca..316e84234 100644 --- a/client/strings/pl.json +++ b/client/strings/pl.json @@ -233,8 +233,8 @@ "LabelAddToCollectionBatch": "Dodaj {0} książki do kolekcji", "LabelAddToPlaylist": "Dodaj do playlisty", "LabelAddToPlaylistBatch": "Dodaj {0} pozycji do playlisty", - "LabelAddedAt": "Dodano", - "LabelAddedDate": "Dodano {0}", + "LabelAddedAt": "Dodano w", + "LabelAddedDate": "Dodano", "LabelAdminUsersOnly": "Tylko użytkownicy administracyjni", "LabelAll": "Wszystkie", "LabelAllEpisodesDownloaded": "Wszystkie odcinki pobrane", diff --git a/client/strings/zh-cn.json b/client/strings/zh-cn.json index 64c41619e..1a95256ab 100644 --- a/client/strings/zh-cn.json +++ b/client/strings/zh-cn.json @@ -275,7 +275,7 @@ "LabelBonus": "额外", "LabelBooks": "图书", "LabelButtonText": "按钮文本", - "LabelByAuthor": "作者: {0}", + "LabelByAuthor": "由 {0}", "LabelChangePassword": "修改密码", "LabelChannels": "声道", "LabelChapterCount": "{0} 章节", diff --git a/package-lock.json b/package-lock.json index 4c9e9b9ea..d703a8edc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "audiobookshelf", - "version": "2.32.0", + "version": "2.31.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "audiobookshelf", - "version": "2.32.0", + "version": "2.31.0", "license": "GPL-3.0", "dependencies": { "axios": "^0.27.2", diff --git a/package.json b/package.json index 2b0d0b6cc..0aaf4f5af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "audiobookshelf", - "version": "2.32.0", + "version": "2.31.0", "buildNumber": 1, "description": "Self-hosted audiobook and podcast server", "main": "index.js", diff --git a/server/providers/Audible.js b/server/providers/Audible.js index 6ba01aa83..2c12ffc1a 100644 --- a/server/providers/Audible.js +++ b/server/providers/Audible.js @@ -57,13 +57,8 @@ class Audible { }) } - let genresCleaned = null - let tagsCleaned = null - - if (genres && Array.isArray(genres)) { - genresCleaned = [...new Set(genres.filter((g) => g.type == 'genre').map((g) => g.name))] - tagsCleaned = [...new Set(genres.filter((g) => g.type == 'tag').map((g) => g.name))] - } + const genresFiltered = genres ? genres.filter((g) => g.type == 'genre').map((g) => g.name) : [] + const tagsFiltered = genres ? genres.filter((g) => g.type == 'tag').map((g) => g.name) : [] return { title, @@ -76,8 +71,8 @@ class Audible { cover: image, asin, isbn, - genres: genresCleaned.length ? genresCleaned : null, - tags: tagsCleaned.length ? tagsCleaned : null, + genres: genresFiltered.length ? genresFiltered : null, + tags: tagsFiltered.length ? tagsFiltered.join(', ') : null, series: series.length ? series : null, language: language ? language.charAt(0).toUpperCase() + language.slice(1) : null, duration: runtimeLengthMin && !isNaN(runtimeLengthMin) ? Number(runtimeLengthMin) : 0, diff --git a/server/providers/CustomProviderAdapter.js b/server/providers/CustomProviderAdapter.js index 5c8cad75a..c079a1280 100644 --- a/server/providers/CustomProviderAdapter.js +++ b/server/providers/CustomProviderAdapter.js @@ -89,27 +89,6 @@ class CustomProviderAdapter { }) .filter((s) => s !== undefined) } - /** - * Validates and dedupes tags/genres array - * Can be comma separated string or array of strings - * @param {string|string[]} tagsGenres - * @returns {string[]} - */ - const validateTagsGenresArray = (tagsGenres) => { - if (!tagsGenres || (typeof tagsGenres !== 'string' && !Array.isArray(tagsGenres))) return undefined - - // If string, split by comma and trim each item - if (typeof tagsGenres === 'string') tagsGenres = tagsGenres.split(',') - // If array, ensure all items are strings - else if (!tagsGenres.every((t) => typeof t === 'string')) return undefined - - // Trim and filter out empty strings - tagsGenres = tagsGenres.map((t) => t.trim()).filter(Boolean) - if (!tagsGenres.length) return undefined - - // Dedup - return [...new Set(tagsGenres)] - } // re-map keys to throw out return matches.map((match) => { @@ -126,8 +105,8 @@ class CustomProviderAdapter { cover: toStringOrUndefined(cover), isbn: toStringOrUndefined(isbn), asin: toStringOrUndefined(asin), - genres: validateTagsGenresArray(genres), - tags: validateTagsGenresArray(tags), + genres: Array.isArray(genres) && genres.every((g) => typeof g === 'string') ? genres : undefined, + tags: toStringOrUndefined(tags), series: validateSeriesArray(series), language: toStringOrUndefined(language), duration: !isNaN(duration) && duration !== null ? Number(duration) : undefined diff --git a/server/scanner/Scanner.js b/server/scanner/Scanner.js index af4405987..206068cc4 100644 --- a/server/scanner/Scanner.js +++ b/server/scanner/Scanner.js @@ -259,17 +259,18 @@ class Scanner { SocketAuthority.emitter('author_added', author.toOldJSON()) // Update filter data Database.addAuthorToFilterData(libraryItem.libraryId, author.name, author.id) + + await Database.bookAuthorModel + .create({ + authorId: author.id, + bookId: libraryItem.media.id + }) + .then(() => { + Logger.info(`[Scanner] quickMatchBookBuildUpdatePayload: Added author "${author.name}" to "${libraryItem.media.title}"`) + libraryItem.media.authors.push(author) + hasAuthorUpdates = true + }) } - await Database.bookAuthorModel - .create({ - authorId: author.id, - bookId: libraryItem.media.id - }) - .then(() => { - Logger.info(`[Scanner] quickMatchBookBuildUpdatePayload: Added author "${author.name}" to "${libraryItem.media.title}"`) - libraryItem.media.authors.push(author) - hasAuthorUpdates = true - }) } const authorsRemoved = libraryItem.media.authors.filter((a) => !matchData.author.find((ma) => ma.toLowerCase() === a.name.toLowerCase())) if (authorsRemoved.length) {