gitextract_pkg28qgc/ ├── .devcontainer/ │ ├── Dockerfile │ ├── dev.js │ ├── devcontainer.json │ └── post-create.sh ├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug.yaml │ │ ├── config.yml │ │ └── feature.yml │ ├── pull_request_template.md │ └── workflows/ │ ├── apply_comments.yaml │ ├── close-issues-on-release.yml │ ├── close_blank_issues.yaml │ ├── codeql.yml │ ├── component-tests.yml │ ├── docker-build.yml │ ├── i18n-integration.yml │ ├── integration-test.yml │ ├── lint-openapi.yml │ ├── notify-abs-windows.yml │ └── unit-tests.yml ├── .gitignore ├── .prettierrc ├── .vscode/ │ ├── extensions.json │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── Dockerfile ├── LICENSE ├── build/ │ ├── debian/ │ │ ├── DEBIAN/ │ │ │ ├── control │ │ │ ├── postinst │ │ │ ├── preinst │ │ │ └── prerm │ │ ├── etc/ │ │ │ └── default/ │ │ │ └── .gitkeep │ │ ├── lib/ │ │ │ └── systemd/ │ │ │ └── system/ │ │ │ └── audiobookshelf.service │ │ └── usr/ │ │ ├── lib/ │ │ │ └── .gitkeep │ │ └── share/ │ │ └── .gitkeep │ └── linuxpackager ├── client/ │ ├── assets/ │ │ ├── absicons.css │ │ ├── app.css │ │ ├── defaultStyles.css │ │ ├── draggable.css │ │ ├── ebooks/ │ │ │ ├── basic.js │ │ │ ├── htmlParser.js │ │ │ └── mobi.js │ │ ├── fonts.css │ │ ├── tailwind.css │ │ ├── transitions.css │ │ └── trix.css │ ├── components/ │ │ ├── app/ │ │ │ ├── Appbar.vue │ │ │ ├── BookShelfCategorized.vue │ │ │ ├── BookShelfRow.vue │ │ │ ├── BookShelfToolbar.vue │ │ │ ├── ConfigSideNav.vue │ │ │ ├── LazyBookshelf.vue │ │ │ ├── MediaPlayerContainer.vue │ │ │ ├── SettingsContent.vue │ │ │ └── SideRail.vue │ │ ├── cards/ │ │ │ ├── AuthorCard.vue │ │ │ ├── AuthorSearchCard.vue │ │ │ ├── BookMatchCard.vue │ │ │ ├── EpisodeSearchCard.vue │ │ │ ├── GenreSearchCard.vue │ │ │ ├── GroupCard.vue │ │ │ ├── ItemSearchCard.vue │ │ │ ├── ItemTaskRunningCard.vue │ │ │ ├── ItemUploadCard.vue │ │ │ ├── LazyBookCard.vue │ │ │ ├── LazyCollectionCard.vue │ │ │ ├── LazyPlaylistCard.vue │ │ │ ├── LazySeriesCard.vue │ │ │ ├── NarratorCard.vue │ │ │ ├── NarratorSearchCard.vue │ │ │ ├── NotificationCard.vue │ │ │ ├── PodcastFeedSummaryCard.vue │ │ │ ├── SeriesSearchCard.vue │ │ │ └── TagSearchCard.vue │ │ ├── content/ │ │ │ └── LibraryItemDetails.vue │ │ ├── controls/ │ │ │ ├── FilterSelect.vue │ │ │ ├── GlobalSearch.vue │ │ │ ├── LibraryFilterSelect.vue │ │ │ ├── LibrarySortSelect.vue │ │ │ ├── PlaybackSpeedControl.vue │ │ │ ├── SortSelect.vue │ │ │ └── VolumeControl.vue │ │ ├── covers/ │ │ │ ├── AuthorImage.vue │ │ │ ├── BookCover.vue │ │ │ ├── CollectionCover.vue │ │ │ ├── GroupCover.vue │ │ │ ├── PlaylistCover.vue │ │ │ └── PreviewCover.vue │ │ ├── modals/ │ │ │ ├── AccountModal.vue │ │ │ ├── AddCustomMetadataProviderModal.vue │ │ │ ├── ApiKeyCreatedModal.vue │ │ │ ├── ApiKeyModal.vue │ │ │ ├── AudioFileDataModal.vue │ │ │ ├── BackupScheduleModal.vue │ │ │ ├── BatchQuickMatchModel.vue │ │ │ ├── BookmarksModal.vue │ │ │ ├── ChaptersModal.vue │ │ │ ├── Dialog.vue │ │ │ ├── EditSeriesInputInnerModal.vue │ │ │ ├── ListeningSessionModal.vue │ │ │ ├── Modal.vue │ │ │ ├── PlayerSettingsModal.vue │ │ │ ├── RawCoverPreviewModal.vue │ │ │ ├── ShareModal.vue │ │ │ ├── SleepTimerModal.vue │ │ │ ├── UploadImageModal.vue │ │ │ ├── authors/ │ │ │ │ └── EditModal.vue │ │ │ ├── bookmarks/ │ │ │ │ └── BookmarkItem.vue │ │ │ ├── changelog/ │ │ │ │ └── ViewModal.vue │ │ │ ├── collections/ │ │ │ │ ├── AddCreateModal.vue │ │ │ │ ├── CollectionItem.vue │ │ │ │ └── EditModal.vue │ │ │ ├── emails/ │ │ │ │ ├── EReaderDeviceModal.vue │ │ │ │ └── UserEReaderDeviceModal.vue │ │ │ ├── item/ │ │ │ │ ├── EditModal.vue │ │ │ │ └── tabs/ │ │ │ │ ├── Chapters.vue │ │ │ │ ├── Cover.vue │ │ │ │ ├── Details.vue │ │ │ │ ├── Episodes.vue │ │ │ │ ├── Files.vue │ │ │ │ ├── Match.vue │ │ │ │ ├── Schedule.vue │ │ │ │ └── Tools.vue │ │ │ ├── libraries/ │ │ │ │ ├── EditLibrary.vue │ │ │ │ ├── EditModal.vue │ │ │ │ ├── LazyFolderChooser.vue │ │ │ │ ├── LibraryScannerSettings.vue │ │ │ │ ├── LibrarySettings.vue │ │ │ │ ├── LibraryTools.vue │ │ │ │ └── ScheduleScan.vue │ │ │ ├── notification/ │ │ │ │ └── NotificationEditModal.vue │ │ │ ├── player/ │ │ │ │ ├── QueueItemRow.vue │ │ │ │ └── QueueItemsModal.vue │ │ │ ├── playlists/ │ │ │ │ ├── AddCreateModal.vue │ │ │ │ ├── EditModal.vue │ │ │ │ └── UserPlaylistItem.vue │ │ │ ├── podcast/ │ │ │ │ ├── EditEpisode.vue │ │ │ │ ├── EpisodeFeed.vue │ │ │ │ ├── NewModal.vue │ │ │ │ ├── OpmlFeedsModal.vue │ │ │ │ ├── RemoveEpisode.vue │ │ │ │ ├── ViewEpisode.vue │ │ │ │ └── tabs/ │ │ │ │ ├── EpisodeDetails.vue │ │ │ │ └── EpisodeMatch.vue │ │ │ └── rssfeed/ │ │ │ ├── OpenCloseModal.vue │ │ │ └── ViewFeedModal.vue │ │ ├── player/ │ │ │ ├── PlayerPlaybackControls.vue │ │ │ ├── PlayerTrackBar.vue │ │ │ └── PlayerUi.vue │ │ ├── prompt/ │ │ │ ├── Confirm.vue │ │ │ └── Dialog.vue │ │ ├── readers/ │ │ │ ├── ComicReader.vue │ │ │ ├── EpubReader.vue │ │ │ ├── MobiReader.vue │ │ │ ├── PdfReader.vue │ │ │ └── Reader.vue │ │ ├── stats/ │ │ │ ├── DailyListeningChart.vue │ │ │ ├── Heatmap.vue │ │ │ ├── PreviewIcons.vue │ │ │ ├── YearInReview.vue │ │ │ ├── YearInReviewBanner.vue │ │ │ ├── YearInReviewServer.vue │ │ │ └── YearInReviewShort.vue │ │ ├── tables/ │ │ │ ├── ApiKeysTable.vue │ │ │ ├── AudioTracksTableRow.vue │ │ │ ├── BackupsTable.vue │ │ │ ├── ChaptersTable.vue │ │ │ ├── CollectionBooksTable.vue │ │ │ ├── CustomMetadataProviderTable.vue │ │ │ ├── EbookFilesTable.vue │ │ │ ├── EbookFilesTableRow.vue │ │ │ ├── LibraryFilesTable.vue │ │ │ ├── LibraryFilesTableRow.vue │ │ │ ├── PlaylistItemsTable.vue │ │ │ ├── TracksTable.vue │ │ │ ├── UploadedFilesTable.vue │ │ │ ├── UsersTable.vue │ │ │ ├── collection/ │ │ │ │ └── BookTableRow.vue │ │ │ ├── library/ │ │ │ │ ├── LibrariesTable.vue │ │ │ │ └── LibraryItem.vue │ │ │ ├── playlist/ │ │ │ │ └── ItemTableRow.vue │ │ │ └── podcast/ │ │ │ ├── DownloadQueueTable.vue │ │ │ ├── LazyEpisodeRow.vue │ │ │ └── LazyEpisodesTable.vue │ │ ├── ui/ │ │ │ ├── Btn.vue │ │ │ ├── Checkbox.vue │ │ │ ├── ContextMenuDropdown.vue │ │ │ ├── Dropdown.vue │ │ │ ├── EditableText.vue │ │ │ ├── FileInput.vue │ │ │ ├── IconBtn.vue │ │ │ ├── InputDropdown.vue │ │ │ ├── LibrariesDropdown.vue │ │ │ ├── LibraryIcon.vue │ │ │ ├── LoadingIndicator.vue │ │ │ ├── MediaIconPicker.vue │ │ │ ├── MultiSelect.vue │ │ │ ├── MultiSelectDropdown.vue │ │ │ ├── MultiSelectQueryInput.vue │ │ │ ├── QueryInput.vue │ │ │ ├── RangeInput.vue │ │ │ ├── ReadIconBtn.vue │ │ │ ├── RichTextEditor.vue │ │ │ ├── SelectInput.vue │ │ │ ├── TextInput.vue │ │ │ ├── TextInputWithLabel.vue │ │ │ ├── TextareaInput.vue │ │ │ ├── TextareaWithLabel.vue │ │ │ ├── TimePicker.vue │ │ │ ├── ToggleBtns.vue │ │ │ ├── ToggleSwitch.vue │ │ │ ├── Tooltip.vue │ │ │ └── VueTrix.vue │ │ └── widgets/ │ │ ├── AbridgedIndicator.vue │ │ ├── Alert.vue │ │ ├── AlreadyInLibraryIndicator.vue │ │ ├── BookDetailsEdit.vue │ │ ├── CoverSizeWidget.vue │ │ ├── CronExpressionBuilder.vue │ │ ├── EncoderOptionsCard.vue │ │ ├── ExplicitIndicator.vue │ │ ├── ItemSlider.vue │ │ ├── LoadingSpinner.vue │ │ ├── MoreMenu.vue │ │ ├── NotificationWidget.vue │ │ ├── OnlineIndicator.vue │ │ ├── PodcastDetailsEdit.vue │ │ ├── PodcastTypeIndicator.vue │ │ ├── RssFeedMetadataBuilder.vue │ │ └── SeriesInputWidget.vue │ ├── cypress/ │ │ ├── support/ │ │ │ ├── commands.js │ │ │ ├── component-index.html │ │ │ └── component.js │ │ └── tests/ │ │ ├── components/ │ │ │ └── cards/ │ │ │ ├── AuthorCard.cy.js │ │ │ ├── ItemSlider.cy.js │ │ │ ├── LazyBookCard.cy.js │ │ │ ├── LazySeriesCard.cy.js │ │ │ └── NarratorCard.cy.js │ │ └── utils/ │ │ └── ElapsedPrettyExtended.cy.js │ ├── cypress.config.js │ ├── layouts/ │ │ ├── blank.vue │ │ ├── default.vue │ │ └── error.vue │ ├── middleware/ │ │ └── authenticated.js │ ├── mixins/ │ │ ├── bookshelfCardsHelpers.js │ │ ├── menuKeyboardNavigation.js │ │ └── uploadHelpers.js │ ├── nuxt.config.js │ ├── package.json │ ├── pages/ │ │ ├── account.vue │ │ ├── audiobook/ │ │ │ └── _id/ │ │ │ ├── chapters.vue │ │ │ ├── edit.vue │ │ │ └── manage.vue │ │ ├── author/ │ │ │ └── _id.vue │ │ ├── batch/ │ │ │ └── index.vue │ │ ├── collection/ │ │ │ └── _id.vue │ │ ├── config/ │ │ │ ├── api-keys/ │ │ │ │ └── index.vue │ │ │ ├── authentication.vue │ │ │ ├── backups.vue │ │ │ ├── email.vue │ │ │ ├── index.vue │ │ │ ├── item-metadata-utils/ │ │ │ │ ├── custom-metadata-providers.vue │ │ │ │ ├── genres.vue │ │ │ │ ├── index.vue │ │ │ │ └── tags.vue │ │ │ ├── libraries.vue │ │ │ ├── log.vue │ │ │ ├── notifications.vue │ │ │ ├── rss-feeds.vue │ │ │ ├── sessions.vue │ │ │ ├── stats.vue │ │ │ └── users/ │ │ │ ├── _id/ │ │ │ │ ├── index.vue │ │ │ │ └── sessions.vue │ │ │ └── index.vue │ │ ├── config.vue │ │ ├── index.vue │ │ ├── item/ │ │ │ └── _id/ │ │ │ └── index.vue │ │ ├── library/ │ │ │ └── _library/ │ │ │ ├── bookshelf/ │ │ │ │ └── _id.vue │ │ │ ├── index.vue │ │ │ ├── narrators.vue │ │ │ ├── podcast/ │ │ │ │ ├── download-queue.vue │ │ │ │ ├── latest.vue │ │ │ │ └── search.vue │ │ │ ├── search.vue │ │ │ ├── series/ │ │ │ │ └── _id.vue │ │ │ └── stats.vue │ │ ├── login.vue │ │ ├── oops.vue │ │ ├── playlist/ │ │ │ └── _id.vue │ │ ├── share/ │ │ │ └── _slug.vue │ │ └── upload/ │ │ └── index.vue │ ├── players/ │ │ ├── AudioTrack.js │ │ ├── CastPlayer.js │ │ ├── LocalAudioPlayer.js │ │ ├── PlayerHandler.js │ │ └── castUtils.js │ ├── plugins/ │ │ ├── axios.js │ │ ├── chromecast.js │ │ ├── constants.js │ │ ├── i18n.js │ │ ├── init.client.js │ │ ├── toast.js │ │ ├── utils.js │ │ └── version.js │ ├── postcss.config.js │ ├── static/ │ │ ├── fonts/ │ │ │ ├── Source_Sans_Pro/ │ │ │ │ └── OFL.txt │ │ │ └── Ubuntu_Mono/ │ │ │ └── UFL.txt │ │ ├── libarchive/ │ │ │ ├── wasm-gen/ │ │ │ │ ├── libarchive.js │ │ │ │ └── libarchive.wasm │ │ │ └── worker-bundle.js │ │ ├── libs/ │ │ │ └── marked/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ └── robots.txt │ ├── store/ │ │ ├── globals.js │ │ ├── index.js │ │ ├── libraries.js │ │ ├── scanners.js │ │ ├── tasks.js │ │ ├── user.js │ │ └── users.js │ └── strings/ │ ├── ar.json │ ├── be.json │ ├── bg.json │ ├── bn.json │ ├── ca.json │ ├── cs.json │ ├── da.json │ ├── de.json │ ├── el.json │ ├── en-us.json │ ├── es.json │ ├── et.json │ ├── eu.json │ ├── fa.json │ ├── fi.json │ ├── fr.json │ ├── gu.json │ ├── he.json │ ├── hi.json │ ├── hr.json │ ├── hu.json │ ├── is.json │ ├── it.json │ ├── ja.json │ ├── ko.json │ ├── lt.json │ ├── nl.json │ ├── no.json │ ├── pl.json │ ├── pt-br.json │ ├── ro.json │ ├── ru.json │ ├── sk.json │ ├── sl.json │ ├── sv.json │ ├── tr.json │ ├── uk.json │ ├── vi-vn.json │ ├── zh-cn.json │ └── zh-tw.json ├── custom-metadata-provider-specification.yaml ├── docker-compose.yml ├── docker-template.xml ├── docs/ │ ├── README.md │ ├── controllers/ │ │ ├── AuthorController.yaml │ │ ├── EmailController.yaml │ │ ├── LibraryController.yaml │ │ ├── NotificationController.yaml │ │ ├── PodcastController.yaml │ │ └── SeriesController.yaml │ ├── objects/ │ │ ├── Folder.yaml │ │ ├── Library.yaml │ │ ├── LibraryItem.yaml │ │ ├── Notification.yaml │ │ ├── entities/ │ │ │ ├── Author.yaml │ │ │ ├── PodcastEpisode.yaml │ │ │ └── Series.yaml │ │ ├── files/ │ │ │ ├── AudioFile.yaml │ │ │ ├── AudioTrack.yaml │ │ │ └── EBookFile.yaml │ │ ├── mediaTypes/ │ │ │ ├── Book.yaml │ │ │ ├── Podcast.yaml │ │ │ └── media.yaml │ │ ├── metadata/ │ │ │ ├── AudioMetaTags.yaml │ │ │ ├── BookMetadata.yaml │ │ │ ├── FileMetadata.yaml │ │ │ └── PodcastMetadata.yaml │ │ └── settings/ │ │ └── EmailSettings.yaml │ ├── openapi.json │ ├── root.yaml │ └── schemas.yaml ├── index.js ├── package.json ├── prod.js ├── readme.md ├── server/ │ ├── Auth.js │ ├── Database.js │ ├── Logger.js │ ├── Server.js │ ├── SocketAuthority.js │ ├── Watcher.js │ ├── auth/ │ │ ├── LocalAuthStrategy.js │ │ ├── OidcAuthStrategy.js │ │ └── TokenManager.js │ ├── controllers/ │ │ ├── ApiKeyController.js │ │ ├── AuthorController.js │ │ ├── BackupController.js │ │ ├── CacheController.js │ │ ├── CollectionController.js │ │ ├── CustomMetadataProviderController.js │ │ ├── EmailController.js │ │ ├── FileSystemController.js │ │ ├── LibraryController.js │ │ ├── LibraryItemController.js │ │ ├── MeController.js │ │ ├── MiscController.js │ │ ├── NotificationController.js │ │ ├── PlaylistController.js │ │ ├── PodcastController.js │ │ ├── RSSFeedController.js │ │ ├── SearchController.js │ │ ├── SeriesController.js │ │ ├── SessionController.js │ │ ├── ShareController.js │ │ ├── StatsController.js │ │ ├── ToolsController.js │ │ └── UserController.js │ ├── finders/ │ │ ├── AuthorFinder.js │ │ ├── BookFinder.js │ │ └── PodcastFinder.js │ ├── libs/ │ │ ├── archiver/ │ │ │ ├── LICENSE │ │ │ ├── archiverUtils/ │ │ │ │ ├── balancedMatch/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ └── index.js │ │ │ │ ├── braceExpansion/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ └── index.js │ │ │ │ ├── file.js │ │ │ │ ├── fsRealpath/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ ├── index.js │ │ │ │ │ └── old.js │ │ │ │ ├── glob/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ ├── common.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── sync.js │ │ │ │ ├── index.js │ │ │ │ ├── inflight/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ └── index.js │ │ │ │ ├── lazystream/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ ├── index.js │ │ │ │ │ └── readable-stream/ │ │ │ │ │ ├── lib/ │ │ │ │ │ │ ├── _stream_duplex.js │ │ │ │ │ │ ├── _stream_passthrough.js │ │ │ │ │ │ ├── _stream_readable.js │ │ │ │ │ │ ├── _stream_transform.js │ │ │ │ │ │ ├── _stream_writable.js │ │ │ │ │ │ └── internal/ │ │ │ │ │ │ └── streams/ │ │ │ │ │ │ ├── BufferList.js │ │ │ │ │ │ ├── destroy.js │ │ │ │ │ │ ├── stream-browser.js │ │ │ │ │ │ └── stream.js │ │ │ │ │ ├── passthrough.js │ │ │ │ │ └── readable.js │ │ │ │ ├── lodash.difference/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ └── index.js │ │ │ │ ├── lodash.flatten/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ └── index.js │ │ │ │ ├── lodash.isplainobject/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ └── index.js │ │ │ │ ├── lodash.union/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ └── index.js │ │ │ │ ├── minimatch/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ └── index.js │ │ │ │ ├── readableStream/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ ├── _stream_duplex.js │ │ │ │ │ ├── _stream_passthrough.js │ │ │ │ │ ├── _stream_readable.js │ │ │ │ │ ├── _stream_transform.js │ │ │ │ │ ├── _stream_writable.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── internal/ │ │ │ │ │ │ ├── streams/ │ │ │ │ │ │ │ ├── add-abort-signal.js │ │ │ │ │ │ │ ├── buffer_list.js │ │ │ │ │ │ │ ├── compose.js │ │ │ │ │ │ │ ├── destroy.js │ │ │ │ │ │ │ ├── duplex.js │ │ │ │ │ │ │ ├── duplexify.js │ │ │ │ │ │ │ ├── end-of-stream.js │ │ │ │ │ │ │ ├── from.js │ │ │ │ │ │ │ ├── lazy_transform.js │ │ │ │ │ │ │ ├── legacy.js │ │ │ │ │ │ │ ├── operators.js │ │ │ │ │ │ │ ├── passthrough.js │ │ │ │ │ │ │ ├── pipeline.js │ │ │ │ │ │ │ ├── readable.js │ │ │ │ │ │ │ ├── state.js │ │ │ │ │ │ │ ├── transform.js │ │ │ │ │ │ │ ├── utils.js │ │ │ │ │ │ │ └── writable.js │ │ │ │ │ │ └── validators.js │ │ │ │ │ ├── ours/ │ │ │ │ │ │ ├── browser.js │ │ │ │ │ │ ├── errors.js │ │ │ │ │ │ ├── primordials.js │ │ │ │ │ │ └── util.js │ │ │ │ │ ├── stream/ │ │ │ │ │ │ └── promises.js │ │ │ │ │ └── stream.js │ │ │ │ ├── safeBuffer/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ └── index.js │ │ │ │ ├── stringDecoder/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ └── index.js │ │ │ │ └── wrappy/ │ │ │ │ ├── LICENSE │ │ │ │ └── index.js │ │ │ ├── buffer-crc32/ │ │ │ │ ├── LICENSE │ │ │ │ └── index.js │ │ │ ├── compress-commons/ │ │ │ │ ├── LICENSE │ │ │ │ ├── archivers/ │ │ │ │ │ ├── archive-entry.js │ │ │ │ │ ├── archive-output-stream.js │ │ │ │ │ └── zip/ │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── general-purpose-bit.js │ │ │ │ │ ├── unix-stat.js │ │ │ │ │ ├── util.js │ │ │ │ │ ├── zip-archive-entry.js │ │ │ │ │ └── zip-archive-output-stream.js │ │ │ │ ├── index.js │ │ │ │ └── util/ │ │ │ │ └── index.js │ │ │ ├── crc32/ │ │ │ │ ├── LICENSE │ │ │ │ └── index.js │ │ │ ├── crc32-stream/ │ │ │ │ ├── LICENSE │ │ │ │ ├── crc32-stream.js │ │ │ │ ├── deflate-crc32-stream.js │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ ├── lib/ │ │ │ │ ├── core.js │ │ │ │ ├── error.js │ │ │ │ └── plugins/ │ │ │ │ ├── json.js │ │ │ │ └── zip.js │ │ │ ├── normalize-path/ │ │ │ │ ├── LICENSE │ │ │ │ └── index.js │ │ │ ├── readdir-glob/ │ │ │ │ ├── LICENSE │ │ │ │ └── index.js │ │ │ └── zip-stream/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── async/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── bcryptjs/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── busboy/ │ │ │ ├── LICENSE │ │ │ ├── index.js │ │ │ ├── types/ │ │ │ │ ├── multipart.js │ │ │ │ └── urlencoded.js │ │ │ └── utils.js │ │ ├── commandLineArgs/ │ │ │ └── index.js │ │ ├── dateAndTime/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── expressFileupload/ │ │ │ ├── LICENSE │ │ │ ├── fileFactory.js │ │ │ ├── index.js │ │ │ ├── isEligibleRequest.js │ │ │ ├── memHandler.js │ │ │ ├── processMultipart.js │ │ │ ├── processNested.js │ │ │ ├── tempFileHandler.js │ │ │ ├── uploadtimer.js │ │ │ └── utilities.js │ │ ├── fastSort/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── fluentFfmpeg/ │ │ │ ├── LICENSE │ │ │ ├── capabilities.js │ │ │ ├── ffprobe.js │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── options/ │ │ │ │ ├── audio.js │ │ │ │ ├── custom.js │ │ │ │ ├── inputs.js │ │ │ │ ├── misc.js │ │ │ │ ├── output.js │ │ │ │ ├── video.js │ │ │ │ └── videosize.js │ │ │ ├── presets/ │ │ │ │ ├── divx.js │ │ │ │ ├── flashvideo.js │ │ │ │ └── podcast.js │ │ │ ├── processor.js │ │ │ ├── recipes.js │ │ │ └── utils.js │ │ ├── fsExtra/ │ │ │ ├── LICENSE │ │ │ ├── copy/ │ │ │ │ ├── copy-sync.js │ │ │ │ ├── copy.js │ │ │ │ └── index.js │ │ │ ├── empty/ │ │ │ │ └── index.js │ │ │ ├── ensure/ │ │ │ │ ├── file.js │ │ │ │ ├── index.js │ │ │ │ ├── link.js │ │ │ │ ├── symlink-paths.js │ │ │ │ ├── symlink-type.js │ │ │ │ └── symlink.js │ │ │ ├── fs/ │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ ├── mkdirs/ │ │ │ │ ├── index.js │ │ │ │ ├── make-dir.js │ │ │ │ └── utils.js │ │ │ ├── move/ │ │ │ │ ├── index.js │ │ │ │ ├── move-sync.js │ │ │ │ └── move.js │ │ │ ├── path-exists/ │ │ │ │ └── index.js │ │ │ ├── remove/ │ │ │ │ ├── index.js │ │ │ │ └── rimraf.js │ │ │ └── util/ │ │ │ ├── stat.js │ │ │ └── utimes.js │ │ ├── fusejs/ │ │ │ └── index.js │ │ ├── imageType/ │ │ │ ├── LICENSE │ │ │ ├── fileType.js │ │ │ └── index.js │ │ ├── isexe/ │ │ │ ├── LICENSE │ │ │ ├── index.js │ │ │ ├── mode.js │ │ │ └── windows.js │ │ ├── jsonwebtoken/ │ │ │ ├── LICENSE │ │ │ ├── decode.js │ │ │ ├── index.js │ │ │ ├── lib/ │ │ │ │ ├── JsonWebTokenError.js │ │ │ │ ├── NotBeforeError.js │ │ │ │ ├── TokenExpiredError.js │ │ │ │ └── timespan.js │ │ │ ├── sign.js │ │ │ └── verify.js │ │ ├── jwa/ │ │ │ ├── LICENSE │ │ │ ├── buffer-equal-constant-time/ │ │ │ │ ├── LICENSE │ │ │ │ └── index.js │ │ │ ├── ecdsa-sig-formatter/ │ │ │ │ ├── LICENSE │ │ │ │ ├── index.js │ │ │ │ └── param-bytes-for-alg.js │ │ │ └── index.js │ │ ├── jws/ │ │ │ ├── LICENSE │ │ │ ├── index.js │ │ │ └── lib/ │ │ │ ├── data-stream.js │ │ │ ├── sign-stream.js │ │ │ ├── tostring.js │ │ │ └── verify-stream.js │ │ ├── libarchive/ │ │ │ ├── LICENSE │ │ │ ├── archive.js │ │ │ ├── libarchiveWorker.js │ │ │ ├── wasm-libarchive.js │ │ │ └── wasm-module.js │ │ ├── lodash.once/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── memorystore/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── nodeCron/ │ │ │ ├── LICENSE │ │ │ ├── background-scheduled-task/ │ │ │ │ ├── daemon.js │ │ │ │ └── index.js │ │ │ ├── convert-expression/ │ │ │ │ ├── asterisk-to-range-conversion.js │ │ │ │ ├── index.js │ │ │ │ ├── month-names-conversion.js │ │ │ │ ├── range-conversion.js │ │ │ │ ├── step-values-conversion.js │ │ │ │ └── week-day-names-conversion.js │ │ │ ├── index.js │ │ │ ├── pattern-validation.js │ │ │ ├── scheduled-task.js │ │ │ ├── scheduler.js │ │ │ ├── storage.js │ │ │ ├── task.js │ │ │ └── time-matcher.js │ │ ├── nodeFfprobe/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── nodeStreamZip/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── passportLocal/ │ │ │ ├── LICENSE │ │ │ ├── index.js │ │ │ └── strategy.js │ │ ├── readChunk/ │ │ │ ├── LICENSE │ │ │ ├── index.js │ │ │ ├── pify.js │ │ │ └── withOpenFile.js │ │ ├── recursiveReaddirAsync/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── requestIp/ │ │ │ ├── LICENSE │ │ │ ├── index.js │ │ │ └── isJs.js │ │ ├── rss/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── sanitizeHtml/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── streamsearch/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── uaParser/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── umzug/ │ │ │ ├── LICENSE │ │ │ ├── index.js │ │ │ ├── storage/ │ │ │ │ ├── contract.js │ │ │ │ ├── index.js │ │ │ │ ├── json.js │ │ │ │ ├── memory.js │ │ │ │ ├── mongodb.js │ │ │ │ └── sequelize.js │ │ │ ├── templates.js │ │ │ ├── types.js │ │ │ └── umzug.js │ │ ├── universalify/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ ├── watcher/ │ │ │ ├── LICENSE │ │ │ ├── aborter/ │ │ │ │ ├── controller.js │ │ │ │ └── signal.js │ │ │ ├── are-shallow-equal.js │ │ │ ├── atomically/ │ │ │ │ ├── consts.js │ │ │ │ ├── index.js │ │ │ │ └── utils/ │ │ │ │ ├── attemptify.js │ │ │ │ ├── fs.js │ │ │ │ ├── fs_handlers.js │ │ │ │ ├── lang.js │ │ │ │ ├── retryify.js │ │ │ │ ├── retryify_queue.js │ │ │ │ ├── scheduler.js │ │ │ │ └── temp.js │ │ │ ├── constants.js │ │ │ ├── debounce.js │ │ │ ├── enums.js │ │ │ ├── is-primitive.js │ │ │ ├── promise-concurrency-limiter.js │ │ │ ├── ripstat/ │ │ │ │ ├── consts.js │ │ │ │ ├── index.js │ │ │ │ └── stats.js │ │ │ ├── string-indexes.js │ │ │ ├── tiny-readdir.js │ │ │ ├── types.js │ │ │ ├── utils.js │ │ │ ├── watcher.js │ │ │ ├── watcher_handler.js │ │ │ ├── watcher_locker.js │ │ │ ├── watcher_locks_resolver.js │ │ │ ├── watcher_poller.js │ │ │ └── watcher_stats.js │ │ ├── which/ │ │ │ ├── LICENSE │ │ │ └── index.js │ │ └── xml/ │ │ ├── LICENSE │ │ ├── escapeForXML.js │ │ └── index.js │ ├── managers/ │ │ ├── AbMergeManager.js │ │ ├── ApiCacheManager.js │ │ ├── AudioMetadataManager.js │ │ ├── BackupManager.js │ │ ├── BinaryManager.js │ │ ├── CacheManager.js │ │ ├── CoverManager.js │ │ ├── CoverSearchManager.js │ │ ├── CronManager.js │ │ ├── EmailManager.js │ │ ├── LogManager.js │ │ ├── MigrationManager.js │ │ ├── NotificationManager.js │ │ ├── PlaybackSessionManager.js │ │ ├── PodcastManager.js │ │ ├── RssFeedManager.js │ │ ├── ShareManager.js │ │ └── TaskManager.js │ ├── migrations/ │ │ ├── changelog.md │ │ ├── readme.md │ │ ├── v2.15.0-series-column-unique.js │ │ ├── v2.15.1-reindex-nocase.js │ │ ├── v2.15.2-index-creation.js │ │ ├── v2.17.0-uuid-replacement.js │ │ ├── v2.17.3-fk-constraints.js │ │ ├── v2.17.4-use-subfolder-for-oidc-redirect-uris.js │ │ ├── v2.17.5-remove-host-from-feed-urls.js │ │ ├── v2.17.6-share-add-isdownloadable.js │ │ ├── v2.17.7-add-indices.js │ │ ├── v2.19.1-copy-title-to-library-items.js │ │ ├── v2.19.4-improve-podcast-queries.js │ │ ├── v2.20.0-improve-author-sort-queries.js │ │ ├── v2.26.0-create-auth-tables.js │ │ └── v2.33.0-add-discover-query-indexes.js │ ├── models/ │ │ ├── ApiKey.js │ │ ├── Author.js │ │ ├── Book.js │ │ ├── BookAuthor.js │ │ ├── BookSeries.js │ │ ├── Collection.js │ │ ├── CollectionBook.js │ │ ├── CustomMetadataProvider.js │ │ ├── Device.js │ │ ├── Feed.js │ │ ├── FeedEpisode.js │ │ ├── Library.js │ │ ├── LibraryFolder.js │ │ ├── LibraryItem.js │ │ ├── MediaItemShare.js │ │ ├── MediaProgress.js │ │ ├── PlaybackSession.js │ │ ├── Playlist.js │ │ ├── PlaylistMediaItem.js │ │ ├── Podcast.js │ │ ├── PodcastEpisode.js │ │ ├── Series.js │ │ ├── Session.js │ │ ├── Setting.js │ │ └── User.js │ ├── objects/ │ │ ├── Backup.js │ │ ├── DailyLog.js │ │ ├── DeviceInfo.js │ │ ├── Notification.js │ │ ├── PlaybackSession.js │ │ ├── PodcastEpisodeDownload.js │ │ ├── Stream.js │ │ ├── Task.js │ │ ├── TrackProgressMonitor.js │ │ ├── files/ │ │ │ ├── AudioFile.js │ │ │ ├── AudioTrack.js │ │ │ ├── EBookFile.js │ │ │ └── LibraryFile.js │ │ ├── metadata/ │ │ │ ├── AudioMetaTags.js │ │ │ └── FileMetadata.js │ │ └── settings/ │ │ ├── EmailSettings.js │ │ ├── NotificationSettings.js │ │ └── ServerSettings.js │ ├── providers/ │ │ ├── Audible.js │ │ ├── AudiobookCovers.js │ │ ├── Audnexus.js │ │ ├── CustomProviderAdapter.js │ │ ├── FantLab.js │ │ ├── GoogleBooks.js │ │ ├── MusicBrainz.js │ │ ├── OpenLibrary.js │ │ └── iTunes.js │ ├── routers/ │ │ ├── ApiRouter.js │ │ ├── HlsRouter.js │ │ └── PublicRouter.js │ ├── scanner/ │ │ ├── AbsMetadataFileScanner.js │ │ ├── AudioFileScanner.js │ │ ├── BookScanner.js │ │ ├── LibraryItemScanData.js │ │ ├── LibraryItemScanner.js │ │ ├── LibraryScan.js │ │ ├── LibraryScanner.js │ │ ├── MediaProbeData.js │ │ ├── NfoFileScanner.js │ │ ├── OpfFileScanner.js │ │ ├── PodcastScanner.js │ │ ├── ScanLogger.js │ │ └── Scanner.js │ └── utils/ │ ├── areEquivalent.js │ ├── comicBookExtractors.js │ ├── constants.js │ ├── ffmpegHelpers.js │ ├── fileUtils.js │ ├── generators/ │ │ ├── abmetadataGenerator.js │ │ ├── hlsPlaylistGenerator.js │ │ └── opmlGenerator.js │ ├── globals.js │ ├── htmlEntities.js │ ├── htmlSanitizer.js │ ├── index.js │ ├── libraryHelpers.js │ ├── longTimeout.js │ ├── migrations/ │ │ ├── absMetadataMigration.js │ │ ├── dbMigration.js │ │ └── oldDbFiles.js │ ├── notifications.js │ ├── parsers/ │ │ ├── parseComicInfoMetadata.js │ │ ├── parseComicMetadata.js │ │ ├── parseEbookMetadata.js │ │ ├── parseEpubMetadata.js │ │ ├── parseFullName.js │ │ ├── parseNameString.js │ │ ├── parseNfoMetadata.js │ │ ├── parseOPML.js │ │ ├── parseOpfMetadata.js │ │ ├── parseOverdriveMediaMarkers.js │ │ └── parseSeriesString.js │ ├── podcastUtils.js │ ├── prober.js │ ├── profiler.js │ ├── queries/ │ │ ├── adminStats.js │ │ ├── authorFilters.js │ │ ├── libraryFilters.js │ │ ├── libraryItemFilters.js │ │ ├── libraryItemsBookFilters.js │ │ ├── libraryItemsPodcastFilters.js │ │ ├── seriesFilters.js │ │ └── userStats.js │ ├── rateLimiterFactory.js │ ├── scandir.js │ ├── stringifySequelizeQuery.js │ └── zipHelpers.js └── test/ └── server/ ├── Logger.test.js ├── controllers/ │ ├── LibraryItemController.test.js │ └── MeController.test.js ├── finders/ │ └── BookFinder.test.js ├── managers/ │ ├── ApiCacheManager.test.js │ ├── BinaryManager.test.js │ ├── MigrationManager.test.js │ └── migrations/ │ ├── v1.0.0-migration.js │ ├── v1.1.0-migration.js │ ├── v1.10.0-migration.js │ └── v1.2.0-migration.js ├── migrations/ │ ├── v0.0.1-migration_example.js │ ├── v0.0.1-migration_example.test.js │ ├── v2.15.0-series-column-unique.test.js │ ├── v2.17.3-fk-constraints.test.js │ ├── v2.17.4-use-subfolder-for-oidc-redirect-uris.test.js │ ├── v2.17.5-remove-host-from-feed-urls.test.js │ ├── v2.17.6-share-add-isdownloadable.test.js │ ├── v2.19.1-copy-title-to-library-items.test.js │ ├── v2.19.4-improve-podcast-queries.test.js │ └── v2.20.0-improve-author-sort-queries.test.js ├── objects/ │ └── TrackProgressMonitor.test.js ├── providers/ │ └── Audible.test.js └── utils/ ├── ffmpegHelpers.test.js ├── fileUtils.test.js ├── parsers/ │ ├── parseNameString.test.js │ ├── parseNfoMetadata.test.js │ └── parseOpfMetadata.test.js ├── scandir.test.js └── stringifySequeslizeQuery.test.js