From 84cbfe870fb81a7a280c1213cced530f0fdc82a9 Mon Sep 17 00:00:00 2001 From: Qstick Date: Tue, 20 Oct 2020 13:46:58 -0400 Subject: [PATCH] Cleanup Search UI, Newznab Caps API --- frontend/src/App/AppRoutes.js | 4 +- frontend/src/History/HistoryRow.js | 13 - .../src/Indexer/History/MovieHistoryRow.js | 9 - .../src/Indexer/MovieCollectionConnector.js | 63 ---- frontend/src/Indexer/MovieFileStatus.css | 4 - frontend/src/Indexer/MovieFileStatus.js | 99 ------ .../src/Indexer/MovieFileStatusConnector.js | 46 --- frontend/src/Indexer/MovieFormats.js | 33 -- frontend/src/Indexer/movieEntities.js | 9 - .../src/Search/Menus/MovieIndexSearchMenu.js | 52 --- .../src/Search/Menus/MovieIndexSortMenu.js | 142 -------- ...FilterMenu.js => SearchIndexFilterMenu.js} | 8 +- .../src/Search/Menus/SearchIndexSortMenu.js | 52 +++ .../src/Search/MovieEditorFooterLabel.css | 8 - frontend/src/Search/MovieEditorFooterLabel.js | 40 --- ...MovieEditorFooter.css => SearchFooter.css} | 0 .../{MovieEditorFooter.js => SearchFooter.js} | 8 +- .../{IndexerIndex.css => SearchIndex.css} | 0 frontend/src/Search/SearchIndex.js | 18 +- ...chConnector.js => SearchIndexConnector.js} | 6 +- .../src/Search/Table/MovieIndexActionsCell.js | 103 ------ ...eIndexHeader.css => SearchIndexHeader.css} | 0 ...vieIndexHeader.js => SearchIndexHeader.js} | 8 +- ...ector.js => SearchIndexHeaderConnector.js} | 4 +- ...nnector.js => SearchIndexItemConnector.js} | 0 .../{MovieIndexRow.css => SearchIndexRow.css} | 0 .../{MovieIndexRow.js => SearchIndexRow.js} | 8 +- ...vieIndexTable.css => SearchIndexTable.css} | 0 ...MovieIndexTable.js => SearchIndexTable.js} | 20 +- ...nector.js => SearchIndexTableConnector.js} | 4 +- .../Instrumentation/NzbDroneLogger.cs | 4 +- .../Analytics/AnalyticsService.cs | 2 +- src/NzbDrone.Core/Datastore/TableMapping.cs | 7 +- src/NzbDrone.Core/History/History.cs | 26 +- .../History/HistoryRepository.cs | 46 +-- src/NzbDrone.Core/History/HistoryService.cs | 40 +-- .../CleanupOrphanedHistoryItems.cs | 10 +- .../IndexerSearch/NzbSearchService.cs | 3 +- .../{ => Definitions}/AwesomeHD/AwesomeHD.cs | 0 .../AwesomeHD/AwesomeHDRequestGenerator.cs | 0 .../AwesomeHD/AwesomeHDRssParser.cs | 0 .../AwesomeHD/AwesomeHDSettings.cs | 0 .../{ => Definitions}/FileList/FileList.cs | 0 .../{ => Definitions}/FileList/FileListApi.cs | 0 .../FileList/FileListParser.cs | 0 .../FileList/FileListRequestGenerator.cs | 0 .../FileList/FileListSettings.cs | 0 .../{ => Definitions}/HDBits/HDBits.cs | 0 .../{ => Definitions}/HDBits/HDBitsApi.cs | 0 .../{ => Definitions}/HDBits/HDBitsInfo.cs | 0 .../{ => Definitions}/HDBits/HDBitsParser.cs | 0 .../HDBits/HDBitsRequestGenerator.cs | 0 .../HDBits/HDBitsSettings.cs | 0 .../IPTorrents/IPTorrents.cs | 0 .../IPTorrents/IPTorrentsRequestGenerator.cs | 0 .../IPTorrents/IPTorrentsSettings.cs | 0 .../{ => Definitions}/Newznab/Newznab.cs | 6 +- .../Newznab/NewznabCapabilities.cs | 0 .../Newznab/NewznabCapabilitiesProvider.cs | 0 .../Newznab/NewznabException.cs | 0 .../Newznab/NewznabRequestGenerator.cs | 0 .../Newznab/NewznabRssParser.cs | 0 .../Newznab/NewznabSettings.cs | 0 .../Indexers/{ => Definitions}/Nyaa/Nyaa.cs | 0 .../Nyaa/NyaaRequestGenerator.cs | 0 .../{ => Definitions}/Nyaa/NyaaSettings.cs | 0 .../PassThePopcorn/PassThePopcorn.cs | 14 +- .../PassThePopcorn/PassThePopcornApi.cs | 0 .../PassThePopcorn/PassThePopcornInfo.cs | 0 .../PassThePopcorn/PassThePopcornParser.cs | 0 .../PassThePopcornRequestGenerator.cs | 0 .../PassThePopcorn/PassThePopcornSettings.cs | 0 .../Indexers/{ => Definitions}/Rarbg/Rarbg.cs | 0 .../{ => Definitions}/Rarbg/RarbgParser.cs | 0 .../Rarbg/RarbgRequestGenerator.cs | 0 .../{ => Definitions}/Rarbg/RarbgResponse.cs | 0 .../{ => Definitions}/Rarbg/RarbgSettings.cs | 0 .../Rarbg/RarbgTokenProvider.cs | 0 .../TorrentPotato/TorrentPotato.cs | 0 .../TorrentPotato/TorrentPotatoParser.cs | 0 .../TorrentPotatoRequestGenerator.cs | 0 .../TorrentPotato/TorrentPotatoResponse.cs | 0 .../TorrentPotato/TorrentPotatoSettings.cs | 0 .../TorrentRss/TorrentRssIndexer.cs | 0 .../TorrentRssIndexerParserSettings.cs | 0 .../TorrentRssIndexerRequestGenerator.cs | 0 .../TorrentRss/TorrentRssIndexerSettings.cs | 0 .../TorrentRss/TorrentRssParserFactory.cs | 0 .../TorrentRss/TorrentRssSettingsDetector.cs | 0 .../{ => Definitions}/Torznab/Torznab.cs | 0 .../Torznab/TorznabException.cs | 0 .../Torznab/TorznabRssParser.cs | 0 .../Torznab/TorznabSettings.cs | 0 src/NzbDrone.Core/Indexers/HttpIndexerBase.cs | 5 +- src/NzbDrone.Core/Indexers/IIndexer.cs | 5 +- src/NzbDrone.Core/Indexers/IndexerBase.cs | 6 +- .../Indexers/IndexerCapabilities.cs | 308 ++++++++++++++++++ src/NzbDrone.Core/Indexers/IndexerCategory.cs | 38 +++ .../Indexers/IndexerDefinition.cs | 5 +- src/NzbDrone.Core/Indexers/IndexerFactory.cs | 6 +- src/Prowlarr.Api.V1/History/HistoryModule.cs | 16 +- .../History/HistoryResource.cs | 8 +- src/Prowlarr.Api.V1/Indexers/IndexerModule.cs | 29 ++ .../Indexers/IndexerResource.cs | 6 +- src/Prowlarr.Api.V1/ProviderModuleBase.cs | 2 +- 105 files changed, 562 insertions(+), 791 deletions(-) delete mode 100644 frontend/src/Indexer/MovieCollectionConnector.js delete mode 100644 frontend/src/Indexer/MovieFileStatus.css delete mode 100644 frontend/src/Indexer/MovieFileStatus.js delete mode 100644 frontend/src/Indexer/MovieFileStatusConnector.js delete mode 100644 frontend/src/Indexer/MovieFormats.js delete mode 100644 frontend/src/Indexer/movieEntities.js delete mode 100644 frontend/src/Search/Menus/MovieIndexSearchMenu.js delete mode 100644 frontend/src/Search/Menus/MovieIndexSortMenu.js rename frontend/src/Search/Menus/{MovieIndexFilterMenu.js => SearchIndexFilterMenu.js} (86%) create mode 100644 frontend/src/Search/Menus/SearchIndexSortMenu.js delete mode 100644 frontend/src/Search/MovieEditorFooterLabel.css delete mode 100644 frontend/src/Search/MovieEditorFooterLabel.js rename frontend/src/Search/{MovieEditorFooter.css => SearchFooter.css} (100%) rename frontend/src/Search/{MovieEditorFooter.js => SearchFooter.js} (92%) rename frontend/src/Search/{IndexerIndex.css => SearchIndex.css} (100%) rename frontend/src/Search/{SearchConnector.js => SearchIndexConnector.js} (94%) delete mode 100644 frontend/src/Search/Table/MovieIndexActionsCell.js rename frontend/src/Search/Table/{MovieIndexHeader.css => SearchIndexHeader.css} (100%) rename frontend/src/Search/Table/{MovieIndexHeader.js => SearchIndexHeader.js} (93%) rename frontend/src/Search/Table/{MovieIndexHeaderConnector.js => SearchIndexHeaderConnector.js} (67%) rename frontend/src/Search/Table/{MovieIndexItemConnector.js => SearchIndexItemConnector.js} (100%) rename frontend/src/Search/Table/{MovieIndexRow.css => SearchIndexRow.css} (100%) rename frontend/src/Search/Table/{MovieIndexRow.js => SearchIndexRow.js} (97%) rename frontend/src/Search/Table/{MovieIndexTable.css => SearchIndexTable.css} (100%) rename frontend/src/Search/Table/{MovieIndexTable.js => SearchIndexTable.js} (85%) rename frontend/src/Search/Table/{MovieIndexTableConnector.js => SearchIndexTableConnector.js} (91%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/AwesomeHD/AwesomeHD.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/AwesomeHD/AwesomeHDRequestGenerator.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/AwesomeHD/AwesomeHDRssParser.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/AwesomeHD/AwesomeHDSettings.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/FileList/FileList.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/FileList/FileListApi.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/FileList/FileListParser.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/FileList/FileListRequestGenerator.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/FileList/FileListSettings.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/HDBits/HDBits.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/HDBits/HDBitsApi.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/HDBits/HDBitsInfo.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/HDBits/HDBitsParser.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/HDBits/HDBitsRequestGenerator.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/HDBits/HDBitsSettings.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/IPTorrents/IPTorrents.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/IPTorrents/IPTorrentsRequestGenerator.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/IPTorrents/IPTorrentsSettings.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Newznab/Newznab.cs (96%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Newznab/NewznabCapabilities.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Newznab/NewznabCapabilitiesProvider.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Newznab/NewznabException.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Newznab/NewznabRequestGenerator.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Newznab/NewznabRssParser.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Newznab/NewznabSettings.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Nyaa/Nyaa.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Nyaa/NyaaRequestGenerator.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Nyaa/NyaaSettings.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/PassThePopcorn/PassThePopcorn.cs (82%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/PassThePopcorn/PassThePopcornApi.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/PassThePopcorn/PassThePopcornInfo.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/PassThePopcorn/PassThePopcornParser.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/PassThePopcorn/PassThePopcornRequestGenerator.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/PassThePopcorn/PassThePopcornSettings.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Rarbg/Rarbg.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Rarbg/RarbgParser.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Rarbg/RarbgRequestGenerator.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Rarbg/RarbgResponse.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Rarbg/RarbgSettings.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Rarbg/RarbgTokenProvider.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/TorrentPotato/TorrentPotato.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/TorrentPotato/TorrentPotatoParser.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/TorrentPotato/TorrentPotatoRequestGenerator.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/TorrentPotato/TorrentPotatoResponse.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/TorrentPotato/TorrentPotatoSettings.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/TorrentRss/TorrentRssIndexer.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/TorrentRss/TorrentRssIndexerParserSettings.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/TorrentRss/TorrentRssIndexerRequestGenerator.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/TorrentRss/TorrentRssIndexerSettings.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/TorrentRss/TorrentRssParserFactory.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/TorrentRss/TorrentRssSettingsDetector.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Torznab/Torznab.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Torznab/TorznabException.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Torznab/TorznabRssParser.cs (100%) rename src/NzbDrone.Core/Indexers/{ => Definitions}/Torznab/TorznabSettings.cs (100%) create mode 100644 src/NzbDrone.Core/Indexers/IndexerCapabilities.cs create mode 100644 src/NzbDrone.Core/Indexers/IndexerCategory.cs diff --git a/frontend/src/App/AppRoutes.js b/frontend/src/App/AppRoutes.js index 3e23005f9..128b77105 100644 --- a/frontend/src/App/AppRoutes.js +++ b/frontend/src/App/AppRoutes.js @@ -5,7 +5,7 @@ import NotFound from 'Components/NotFound'; import Switch from 'Components/Router/Switch'; import HistoryConnector from 'History/HistoryConnector'; import IndexerIndexConnector from 'Indexer/Index/IndexerIndexConnector'; -import SearchConnector from 'Search/SearchConnector'; +import SearchIndexConnector from 'Search/SearchIndexConnector'; import GeneralSettingsConnector from 'Settings/General/GeneralSettingsConnector'; import IndexerSettingsConnector from 'Settings/Indexers/IndexerSettingsConnector'; import NotificationSettings from 'Settings/Notifications/NotificationSettings'; @@ -65,7 +65,7 @@ function AppRoutes(props) { {/* diff --git a/frontend/src/History/HistoryRow.js b/frontend/src/History/HistoryRow.js index 072a49c6d..0bf96cb9e 100644 --- a/frontend/src/History/HistoryRow.js +++ b/frontend/src/History/HistoryRow.js @@ -5,7 +5,6 @@ import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellCo import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableRow from 'Components/Table/TableRow'; import { icons } from 'Helpers/Props'; -import MovieFormats from 'Indexer/MovieFormats'; import MovieLanguage from 'Indexer/MovieLanguage'; import MovieQuality from 'Indexer/MovieQuality'; import MovieTitleLink from 'Indexer/MovieTitleLink'; @@ -54,7 +53,6 @@ class HistoryRow extends Component { const { movie, quality, - customFormats, languages, qualityCutoffNotMet, eventType, @@ -127,16 +125,6 @@ class HistoryRow extends Component { ); } - if (name === 'customFormats') { - return ( - - - - ); - } - if (name === 'date') { return ( - - - - @@ -157,7 +149,6 @@ MovieHistoryRow.propTypes = { sourceTitle: PropTypes.string.isRequired, languages: PropTypes.arrayOf(PropTypes.object).isRequired, quality: PropTypes.object.isRequired, - customFormats: PropTypes.arrayOf(PropTypes.object).isRequired, qualityCutoffNotMet: PropTypes.bool.isRequired, date: PropTypes.string.isRequired, data: PropTypes.object.isRequired, diff --git a/frontend/src/Indexer/MovieCollectionConnector.js b/frontend/src/Indexer/MovieCollectionConnector.js deleted file mode 100644 index 09bf0827a..000000000 --- a/frontend/src/Indexer/MovieCollectionConnector.js +++ /dev/null @@ -1,63 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createIndexerSelector from 'Store/Selectors/createIndexerSelector'; -import createMovieCollectionListSelector from 'Store/Selectors/createMovieCollectionListSelector'; -import MovieCollection from './MovieCollection'; - -function createMapStateToProps() { - return createSelector( - createIndexerSelector(), - createMovieCollectionListSelector(), - (movie, collectionList) => { - const { - monitored, - qualityProfileId, - minimumAvailability - } = movie; - - return { - collectionList, - monitored, - qualityProfileId, - minimumAvailability - }; - } - ); -} - -class MovieCollectionConnector extends Component { - - // - // Listeners - - onMonitorTogglePress = (monitored) => { - - } - - // - // Render - - render() { - return ( - - ); - } -} - -MovieCollectionConnector.propTypes = { - tmdbId: PropTypes.number.isRequired, - movieId: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - collectionList: PropTypes.object, - monitored: PropTypes.bool.isRequired, - qualityProfileId: PropTypes.number.isRequired, - minimumAvailability: PropTypes.string.isRequired, - isSaving: PropTypes.bool.isRequired -}; - -export default connect(createMapStateToProps)(MovieCollectionConnector); diff --git a/frontend/src/Indexer/MovieFileStatus.css b/frontend/src/Indexer/MovieFileStatus.css deleted file mode 100644 index 3833887df..000000000 --- a/frontend/src/Indexer/MovieFileStatus.css +++ /dev/null @@ -1,4 +0,0 @@ -.center { - display: flex; - justify-content: center; -} diff --git a/frontend/src/Indexer/MovieFileStatus.js b/frontend/src/Indexer/MovieFileStatus.js deleted file mode 100644 index 14f4200e7..000000000 --- a/frontend/src/Indexer/MovieFileStatus.js +++ /dev/null @@ -1,99 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Label from 'Components/Label'; -import { kinds } from 'Helpers/Props'; -import MovieQuality from 'Indexer/MovieQuality'; -import getQueueStatusText from 'Utilities/Movie/getQueueStatusText'; -import translate from 'Utilities/String/translate'; -import styles from './MovieFileStatus.css'; - -function MovieFileStatus(props) { - const { - isAvailable, - monitored, - movieFile, - queueStatus, - queueState - } = props; - - const hasMovieFile = !!movieFile; - const hasReleased = isAvailable; - - if (queueStatus) { - const queueStatusText = getQueueStatusText(queueStatus, queueState); - - return ( -
- -
- ); - } - - if (hasMovieFile) { - const quality = movieFile.quality; - - return ( -
- -
- ); - } - - if (!monitored) { - return ( -
- -
- ); - } - - if (hasReleased) { - return ( -
- -
- ); - } - - return ( -
- -
- ); -} - -MovieFileStatus.propTypes = { - isAvailable: PropTypes.bool, - monitored: PropTypes.bool.isRequired, - movieFile: PropTypes.object, - queueStatus: PropTypes.string, - queueState: PropTypes.string -}; - -export default MovieFileStatus; diff --git a/frontend/src/Indexer/MovieFileStatusConnector.js b/frontend/src/Indexer/MovieFileStatusConnector.js deleted file mode 100644 index 80e831048..000000000 --- a/frontend/src/Indexer/MovieFileStatusConnector.js +++ /dev/null @@ -1,46 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createIndexerSelector from 'Store/Selectors/createIndexerSelector'; -import MovieFileStatus from './MovieFileStatus'; - -function createMapStateToProps() { - return createSelector( - createIndexerSelector(), - (movie) => { - return { - inCinemas: movie.inCinemas, - isAvailable: movie.isAvailable, - monitored: movie.monitored, - grabbed: movie.grabbed, - movieFile: movie.movieFile - }; - } - ); -} - -const mapDispatchToProps = { -}; - -class MovieFileStatusConnector extends Component { - - // - // Render - - render() { - return ( - - ); - } -} - -MovieFileStatusConnector.propTypes = { - movieId: PropTypes.number.isRequired, - queueStatus: PropTypes.string, - queueState: PropTypes.string -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(MovieFileStatusConnector); diff --git a/frontend/src/Indexer/MovieFormats.js b/frontend/src/Indexer/MovieFormats.js deleted file mode 100644 index 9e8051be3..000000000 --- a/frontend/src/Indexer/MovieFormats.js +++ /dev/null @@ -1,33 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Label from 'Components/Label'; -import { kinds } from 'Helpers/Props'; - -function MovieFormats({ formats }) { - return ( -
- { - formats.map((format) => { - return ( - - ); - }) - } -
- ); -} - -MovieFormats.propTypes = { - formats: PropTypes.arrayOf(PropTypes.object).isRequired -}; - -MovieFormats.defaultProps = { - formats: [] -}; - -export default MovieFormats; diff --git a/frontend/src/Indexer/movieEntities.js b/frontend/src/Indexer/movieEntities.js deleted file mode 100644 index 32b276a4b..000000000 --- a/frontend/src/Indexer/movieEntities.js +++ /dev/null @@ -1,9 +0,0 @@ -export const CALENDAR = 'calendar'; -export const MOVIES = 'movies'; -export const INTERACTIVE_IMPORT = 'interactiveImport.movies'; - -export default { - CALENDAR, - MOVIES, - INTERACTIVE_IMPORT -}; diff --git a/frontend/src/Search/Menus/MovieIndexSearchMenu.js b/frontend/src/Search/Menus/MovieIndexSearchMenu.js deleted file mode 100644 index 91c147a47..000000000 --- a/frontend/src/Search/Menus/MovieIndexSearchMenu.js +++ /dev/null @@ -1,52 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Menu from 'Components/Menu/Menu'; -import MenuContent from 'Components/Menu/MenuContent'; -import SearchMenuItem from 'Components/Menu/SearchMenuItem'; -import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton'; -import { align, icons } from 'Helpers/Props'; - -class MovieIndexSearchMenu extends Component { - - render() { - const { - isDisabled, - onSearchPress - } = this.props; - - return ( - - - - - Search Missing - - - - Search Cutoff Unmet - - - - ); - } -} - -MovieIndexSearchMenu.propTypes = { - isDisabled: PropTypes.bool.isRequired, - onSearchPress: PropTypes.func.isRequired -}; - -export default MovieIndexSearchMenu; diff --git a/frontend/src/Search/Menus/MovieIndexSortMenu.js b/frontend/src/Search/Menus/MovieIndexSortMenu.js deleted file mode 100644 index fe006f414..000000000 --- a/frontend/src/Search/Menus/MovieIndexSortMenu.js +++ /dev/null @@ -1,142 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import MenuContent from 'Components/Menu/MenuContent'; -import SortMenu from 'Components/Menu/SortMenu'; -import SortMenuItem from 'Components/Menu/SortMenuItem'; -import { align, sortDirections } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -function MovieIndexSortMenu(props) { - const { - sortKey, - sortDirection, - isDisabled, - onSortSelect - } = props; - - return ( - - - - Monitored/Status - - - - {translate('Title')} - - - - {translate('Studio')} - - - - {translate('QualityProfile')} - - - - {translate('Added')} - - - - {translate('Year')} - - - - {translate('InCinemas')} - - - - {translate('PhysicalRelease')} - - - - {translate('DigitalRelease')} - - - - {translate('Path')} - - - - {translate('SizeOnDisk')} - - - - {translate('Certification')} - - - - ); -} - -MovieIndexSortMenu.propTypes = { - sortKey: PropTypes.string, - sortDirection: PropTypes.oneOf(sortDirections.all), - isDisabled: PropTypes.bool.isRequired, - onSortSelect: PropTypes.func.isRequired -}; - -export default MovieIndexSortMenu; diff --git a/frontend/src/Search/Menus/MovieIndexFilterMenu.js b/frontend/src/Search/Menus/SearchIndexFilterMenu.js similarity index 86% rename from frontend/src/Search/Menus/MovieIndexFilterMenu.js rename to frontend/src/Search/Menus/SearchIndexFilterMenu.js index a2846512c..b59c6e780 100644 --- a/frontend/src/Search/Menus/MovieIndexFilterMenu.js +++ b/frontend/src/Search/Menus/SearchIndexFilterMenu.js @@ -4,7 +4,7 @@ import FilterMenu from 'Components/Menu/FilterMenu'; import { align } from 'Helpers/Props'; import MovieIndexFilterModalConnector from 'Indexer/Index/MovieIndexFilterModalConnector'; -function MovieIndexFilterMenu(props) { +function SearchIndexFilterMenu(props) { const { selectedFilterKey, filters, @@ -26,7 +26,7 @@ function MovieIndexFilterMenu(props) { ); } -MovieIndexFilterMenu.propTypes = { +SearchIndexFilterMenu.propTypes = { selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, filters: PropTypes.arrayOf(PropTypes.object).isRequired, customFilters: PropTypes.arrayOf(PropTypes.object).isRequired, @@ -34,8 +34,8 @@ MovieIndexFilterMenu.propTypes = { onFilterSelect: PropTypes.func.isRequired }; -MovieIndexFilterMenu.defaultProps = { +SearchIndexFilterMenu.defaultProps = { showCustomFilters: false }; -export default MovieIndexFilterMenu; +export default SearchIndexFilterMenu; diff --git a/frontend/src/Search/Menus/SearchIndexSortMenu.js b/frontend/src/Search/Menus/SearchIndexSortMenu.js new file mode 100644 index 000000000..3e4ae0574 --- /dev/null +++ b/frontend/src/Search/Menus/SearchIndexSortMenu.js @@ -0,0 +1,52 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import MenuContent from 'Components/Menu/MenuContent'; +import SortMenu from 'Components/Menu/SortMenu'; +import SortMenuItem from 'Components/Menu/SortMenuItem'; +import { align, sortDirections } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; + +function SearchIndexSortMenu(props) { + const { + sortKey, + sortDirection, + isDisabled, + onSortSelect + } = props; + + return ( + + + + Monitored/Status + + + + {translate('Title')} + + + + ); +} + +SearchIndexSortMenu.propTypes = { + sortKey: PropTypes.string, + sortDirection: PropTypes.oneOf(sortDirections.all), + isDisabled: PropTypes.bool.isRequired, + onSortSelect: PropTypes.func.isRequired +}; + +export default SearchIndexSortMenu; diff --git a/frontend/src/Search/MovieEditorFooterLabel.css b/frontend/src/Search/MovieEditorFooterLabel.css deleted file mode 100644 index 9b4b40be6..000000000 --- a/frontend/src/Search/MovieEditorFooterLabel.css +++ /dev/null @@ -1,8 +0,0 @@ -.label { - margin-bottom: 3px; - font-weight: bold; -} - -.savingIcon { - margin-left: 8px; -} diff --git a/frontend/src/Search/MovieEditorFooterLabel.js b/frontend/src/Search/MovieEditorFooterLabel.js deleted file mode 100644 index 805ecd39e..000000000 --- a/frontend/src/Search/MovieEditorFooterLabel.js +++ /dev/null @@ -1,40 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import SpinnerIcon from 'Components/SpinnerIcon'; -import { icons } from 'Helpers/Props'; -import styles from './MovieEditorFooterLabel.css'; - -function MovieEditorFooterLabel(props) { - const { - className, - label, - isSaving - } = props; - - return ( -
- {label} - - { - isSaving && - - } -
- ); -} - -MovieEditorFooterLabel.propTypes = { - className: PropTypes.string.isRequired, - label: PropTypes.string.isRequired, - isSaving: PropTypes.bool.isRequired -}; - -MovieEditorFooterLabel.defaultProps = { - className: styles.label -}; - -export default MovieEditorFooterLabel; diff --git a/frontend/src/Search/MovieEditorFooter.css b/frontend/src/Search/SearchFooter.css similarity index 100% rename from frontend/src/Search/MovieEditorFooter.css rename to frontend/src/Search/SearchFooter.css diff --git a/frontend/src/Search/MovieEditorFooter.js b/frontend/src/Search/SearchFooter.js similarity index 92% rename from frontend/src/Search/MovieEditorFooter.js rename to frontend/src/Search/SearchFooter.js index 2fc16782b..f1131c494 100644 --- a/frontend/src/Search/MovieEditorFooter.js +++ b/frontend/src/Search/SearchFooter.js @@ -3,9 +3,9 @@ import React, { Component } from 'react'; import TextInput from 'Components/Form/TextInput'; import SpinnerButton from 'Components/Link/SpinnerButton'; import PageContentFooter from 'Components/Page/PageContentFooter'; -import styles from './MovieEditorFooter.css'; +import styles from './SearchFooter.css'; -class MovieEditorFooter extends Component { +class SearchFooter extends Component { // // Lifecycle @@ -87,10 +87,10 @@ class MovieEditorFooter extends Component { } } -MovieEditorFooter.propTypes = { +SearchFooter.propTypes = { isFetching: PropTypes.bool.isRequired, onSearchPress: PropTypes.func.isRequired, searchError: PropTypes.object }; -export default MovieEditorFooter; +export default SearchFooter; diff --git a/frontend/src/Search/IndexerIndex.css b/frontend/src/Search/SearchIndex.css similarity index 100% rename from frontend/src/Search/IndexerIndex.css rename to frontend/src/Search/SearchIndex.css diff --git a/frontend/src/Search/SearchIndex.js b/frontend/src/Search/SearchIndex.js index b588e6296..21bf3d36b 100644 --- a/frontend/src/Search/SearchIndex.js +++ b/frontend/src/Search/SearchIndex.js @@ -16,14 +16,14 @@ import * as keyCodes from 'Utilities/Constants/keyCodes'; import getErrorMessage from 'Utilities/Object/getErrorMessage'; import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder'; import translate from 'Utilities/String/translate'; -import MovieIndexFilterMenu from './Menus/MovieIndexFilterMenu'; -import MovieIndexSortMenu from './Menus/MovieIndexSortMenu'; -import MovieEditorFooter from './MovieEditorFooter.js'; -import MovieIndexTableConnector from './Table/MovieIndexTableConnector'; -import styles from './IndexerIndex.css'; +import SearchIndexFilterMenu from './Menus/SearchIndexFilterMenu'; +import SearchIndexSortMenu from './Menus/SearchIndexSortMenu'; +import SearchFooter from './SearchFooter.js'; +import SearchIndexTableConnector from './Table/SearchIndexTableConnector'; +import styles from './SearchIndex.css'; function getViewComponent() { - return MovieIndexTableConnector; + return SearchIndexTableConnector; } class SearchIndex extends Component { @@ -194,14 +194,14 @@ class SearchIndex extends Component { - - - diff --git a/frontend/src/Search/SearchConnector.js b/frontend/src/Search/SearchIndexConnector.js similarity index 94% rename from frontend/src/Search/SearchConnector.js rename to frontend/src/Search/SearchIndexConnector.js index 39c91797f..da8e98559 100644 --- a/frontend/src/Search/SearchConnector.js +++ b/frontend/src/Search/SearchIndexConnector.js @@ -45,7 +45,7 @@ function createMapDispatchToProps(dispatch, props) { }; } -class SearchConnector extends Component { +class SearchIndexConnector extends Component { onScroll = ({ scrollTop }) => { scrollPositions.movieIndex = scrollTop; @@ -64,13 +64,13 @@ class SearchConnector extends Component { } } -SearchConnector.propTypes = { +SearchIndexConnector.propTypes = { isSmallScreen: PropTypes.bool.isRequired, onSearchPress: PropTypes.func.isRequired, items: PropTypes.arrayOf(PropTypes.object) }; export default withScrollPosition( - connect(createMapStateToProps, createMapDispatchToProps)(SearchConnector), + connect(createMapStateToProps, createMapDispatchToProps)(SearchIndexConnector), 'releases' ); diff --git a/frontend/src/Search/Table/MovieIndexActionsCell.js b/frontend/src/Search/Table/MovieIndexActionsCell.js deleted file mode 100644 index 554ec54d3..000000000 --- a/frontend/src/Search/Table/MovieIndexActionsCell.js +++ /dev/null @@ -1,103 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import IconButton from 'Components/Link/IconButton'; -import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; -import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell'; -import { icons } from 'Helpers/Props'; -import DeleteMovieModal from 'Indexer/Delete/DeleteMovieModal'; -import EditMovieModalConnector from 'Indexer/Edit/EditMovieModalConnector'; -import translate from 'Utilities/String/translate'; - -class MovieIndexActionsCell extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isEditMovieModalOpen: false, - isDeleteMovieModalOpen: false - }; - } - - // - // Listeners - - onEditMoviePress = () => { - this.setState({ isEditMovieModalOpen: true }); - } - - onEditMovieModalClose = () => { - this.setState({ isEditMovieModalOpen: false }); - } - - onDeleteMoviePress = () => { - this.setState({ - isEditMovieModalOpen: false, - isDeleteMovieModalOpen: true - }); - } - - onDeleteMovieModalClose = () => { - this.setState({ isDeleteMovieModalOpen: false }); - } - - // - // Render - - render() { - const { - id, - isRefreshingMovie, - onRefreshMoviePress, - ...otherProps - } = this.props; - - const { - isEditMovieModalOpen, - isDeleteMovieModalOpen - } = this.state; - - return ( - - - - - - - - - - ); - } -} - -MovieIndexActionsCell.propTypes = { - id: PropTypes.number.isRequired, - isRefreshingMovie: PropTypes.bool.isRequired, - onRefreshMoviePress: PropTypes.func.isRequired -}; - -export default MovieIndexActionsCell; diff --git a/frontend/src/Search/Table/MovieIndexHeader.css b/frontend/src/Search/Table/SearchIndexHeader.css similarity index 100% rename from frontend/src/Search/Table/MovieIndexHeader.css rename to frontend/src/Search/Table/SearchIndexHeader.css diff --git a/frontend/src/Search/Table/MovieIndexHeader.js b/frontend/src/Search/Table/SearchIndexHeader.js similarity index 93% rename from frontend/src/Search/Table/MovieIndexHeader.js rename to frontend/src/Search/Table/SearchIndexHeader.js index edd07e056..df132e0a7 100644 --- a/frontend/src/Search/Table/MovieIndexHeader.js +++ b/frontend/src/Search/Table/SearchIndexHeader.js @@ -5,9 +5,9 @@ import TableOptionsModal from 'Components/Table/TableOptions/TableOptionsModal'; import VirtualTableHeader from 'Components/Table/VirtualTableHeader'; import VirtualTableHeaderCell from 'Components/Table/VirtualTableHeaderCell'; import { icons } from 'Helpers/Props'; -import styles from './MovieIndexHeader.css'; +import styles from './SearchIndexHeader.css'; -class MovieIndexHeader extends Component { +class SearchIndexHeader extends Component { // // Lifecycle @@ -98,9 +98,9 @@ class MovieIndexHeader extends Component { } } -MovieIndexHeader.propTypes = { +SearchIndexHeader.propTypes = { columns: PropTypes.arrayOf(PropTypes.object).isRequired, onTableOptionChange: PropTypes.func.isRequired }; -export default MovieIndexHeader; +export default SearchIndexHeader; diff --git a/frontend/src/Search/Table/MovieIndexHeaderConnector.js b/frontend/src/Search/Table/SearchIndexHeaderConnector.js similarity index 67% rename from frontend/src/Search/Table/MovieIndexHeaderConnector.js rename to frontend/src/Search/Table/SearchIndexHeaderConnector.js index 7361b0fef..b2d13b3d8 100644 --- a/frontend/src/Search/Table/MovieIndexHeaderConnector.js +++ b/frontend/src/Search/Table/SearchIndexHeaderConnector.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux'; import { setMovieTableOption } from 'Store/Actions/indexerIndexActions'; -import MovieIndexHeader from './MovieIndexHeader'; +import SearchIndexHeader from './SearchIndexHeader'; function createMapDispatchToProps(dispatch, props) { return { @@ -10,4 +10,4 @@ function createMapDispatchToProps(dispatch, props) { }; } -export default connect(undefined, createMapDispatchToProps)(MovieIndexHeader); +export default connect(undefined, createMapDispatchToProps)(SearchIndexHeader); diff --git a/frontend/src/Search/Table/MovieIndexItemConnector.js b/frontend/src/Search/Table/SearchIndexItemConnector.js similarity index 100% rename from frontend/src/Search/Table/MovieIndexItemConnector.js rename to frontend/src/Search/Table/SearchIndexItemConnector.js diff --git a/frontend/src/Search/Table/MovieIndexRow.css b/frontend/src/Search/Table/SearchIndexRow.css similarity index 100% rename from frontend/src/Search/Table/MovieIndexRow.css rename to frontend/src/Search/Table/SearchIndexRow.css diff --git a/frontend/src/Search/Table/MovieIndexRow.js b/frontend/src/Search/Table/SearchIndexRow.js similarity index 97% rename from frontend/src/Search/Table/MovieIndexRow.js rename to frontend/src/Search/Table/SearchIndexRow.js index a1eaba3cb..654135593 100644 --- a/frontend/src/Search/Table/MovieIndexRow.js +++ b/frontend/src/Search/Table/SearchIndexRow.js @@ -12,9 +12,9 @@ import formatBytes from 'Utilities/Number/formatBytes'; import translate from 'Utilities/String/translate'; import Peers from './Peers'; import ProtocolLabel from './ProtocolLabel'; -import styles from './MovieIndexRow.css'; +import styles from './SearchIndexRow.css'; -class MovieIndexRow extends Component { +class SearchIndexRow extends Component { // // Render @@ -190,7 +190,7 @@ class MovieIndexRow extends Component { } } -MovieIndexRow.propTypes = { +SearchIndexRow.propTypes = { guid: PropTypes.string.isRequired, protocol: PropTypes.string.isRequired, age: PropTypes.number.isRequired, @@ -210,4 +210,4 @@ MovieIndexRow.propTypes = { timeFormat: PropTypes.string.isRequired }; -export default MovieIndexRow; +export default SearchIndexRow; diff --git a/frontend/src/Search/Table/MovieIndexTable.css b/frontend/src/Search/Table/SearchIndexTable.css similarity index 100% rename from frontend/src/Search/Table/MovieIndexTable.css rename to frontend/src/Search/Table/SearchIndexTable.css diff --git a/frontend/src/Search/Table/MovieIndexTable.js b/frontend/src/Search/Table/SearchIndexTable.js similarity index 85% rename from frontend/src/Search/Table/MovieIndexTable.js rename to frontend/src/Search/Table/SearchIndexTable.js index f076a7170..4490a8499 100644 --- a/frontend/src/Search/Table/MovieIndexTable.js +++ b/frontend/src/Search/Table/SearchIndexTable.js @@ -4,12 +4,12 @@ import VirtualTable from 'Components/Table/VirtualTable'; import VirtualTableRow from 'Components/Table/VirtualTableRow'; import { sortDirections } from 'Helpers/Props'; import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter'; -import MovieIndexHeaderConnector from './MovieIndexHeaderConnector'; -import MovieIndexItemConnector from './MovieIndexItemConnector'; -import MovieIndexRow from './MovieIndexRow'; -import styles from './MovieIndexTable.css'; +import SearchIndexHeaderConnector from './SearchIndexHeaderConnector'; +import SearchIndexItemConnector from './SearchIndexItemConnector'; +import SearchIndexRow from './SearchIndexRow'; +import styles from './SearchIndexTable.css'; -class MovieIndexTable extends Component { +class SearchIndexTable extends Component { // // Lifecycle @@ -58,9 +58,9 @@ class MovieIndexTable extends Component { key={key} style={style} > - () { Page = 0, PageSize = 1, SortKey = "date", SortDirection = SortDirection.Descending }); + var lastRecord = _historyService.Paged(new PagingSpec() { Page = 0, PageSize = 1, SortKey = "date", SortDirection = SortDirection.Descending }); var monthAgo = DateTime.UtcNow.AddMonths(-1); return lastRecord.Records.Any(v => v.Date > monthAgo); diff --git a/src/NzbDrone.Core/Datastore/TableMapping.cs b/src/NzbDrone.Core/Datastore/TableMapping.cs index 0e78821d1..94f96d974 100644 --- a/src/NzbDrone.Core/Datastore/TableMapping.cs +++ b/src/NzbDrone.Core/Datastore/TableMapping.cs @@ -45,17 +45,14 @@ namespace NzbDrone.Core.Datastore .Ignore(i => i.Privacy) .Ignore(i => i.SupportsRss) .Ignore(i => i.SupportsSearch) - .Ignore(i => i.SupportsBooks) - .Ignore(i => i.SupportsMusic) - .Ignore(i => i.SupportsMovies) - .Ignore(i => i.SupportsTv) + .Ignore(i => i.Capabilities) .Ignore(d => d.Tags); Mapper.Entity("Notifications").RegisterModel() .Ignore(x => x.ImplementationName) .Ignore(i => i.SupportsOnHealthIssue); - Mapper.Entity("History").RegisterModel(); + Mapper.Entity("History").RegisterModel(); Mapper.Entity("Logs").RegisterModel(); diff --git a/src/NzbDrone.Core/History/History.cs b/src/NzbDrone.Core/History/History.cs index 93b2bf3c3..1481626ca 100644 --- a/src/NzbDrone.Core/History/History.cs +++ b/src/NzbDrone.Core/History/History.cs @@ -1,42 +1,28 @@ using System; using System.Collections.Generic; using NzbDrone.Core.Datastore; -using NzbDrone.Core.Languages; namespace NzbDrone.Core.History { - public class MovieHistory : ModelBase + public class History : ModelBase { - public const string DOWNLOAD_CLIENT = "downloadClient"; - - public MovieHistory() + public History() { Data = new Dictionary(StringComparer.OrdinalIgnoreCase); } - public int MovieId { get; set; } + public int IndexerId { get; set; } public string SourceTitle { get; set; } public DateTime Date { get; set; } - public MovieHistoryEventType EventType { get; set; } + public HistoryEventType EventType { get; set; } public Dictionary Data { get; set; } - public List Languages { get; set; } public string DownloadId { get; set; } } - public enum MovieHistoryEventType + public enum HistoryEventType { Unknown = 0, - Grabbed = 1, - - // SeriesFolderImported = 2, // deprecated - DownloadFolderImported = 3, - DownloadFailed = 4, - - // EpisodeFileDeleted = 5, // deprecated - MovieFileDeleted = 6, - MovieFolderImported = 7, // not used yet - MovieFileRenamed = 8, - DownloadIgnored = 9 + ReleaseGrabbed = 1 } } diff --git a/src/NzbDrone.Core/History/HistoryRepository.cs b/src/NzbDrone.Core/History/HistoryRepository.cs index 698b8d71b..ead83511c 100644 --- a/src/NzbDrone.Core/History/HistoryRepository.cs +++ b/src/NzbDrone.Core/History/HistoryRepository.cs @@ -6,47 +6,47 @@ using NzbDrone.Core.Messaging.Events; namespace NzbDrone.Core.History { - public interface IHistoryRepository : IBasicRepository + public interface IHistoryRepository : IBasicRepository { - MovieHistory MostRecentForDownloadId(string downloadId); - List FindByDownloadId(string downloadId); - List FindDownloadHistory(int movieId); - List GetByMovieId(int movieId, MovieHistoryEventType? eventType); - void DeleteForMovies(List movieIds); - MovieHistory MostRecentForMovie(int movieId); - List Since(DateTime date, MovieHistoryEventType? eventType); + History MostRecentForDownloadId(string downloadId); + List FindByDownloadId(string downloadId); + List FindDownloadHistory(int indexerId); + List GetByIndexerId(int indexerId, HistoryEventType? eventType); + void DeleteForIndexers(List indexerIds); + History MostRecentForIndexer(int indexerId); + List Since(DateTime date, HistoryEventType? eventType); } - public class HistoryRepository : BasicRepository, IHistoryRepository + public class HistoryRepository : BasicRepository, IHistoryRepository { public HistoryRepository(IMainDatabase database, IEventAggregator eventAggregator) : base(database, eventAggregator) { } - public MovieHistory MostRecentForDownloadId(string downloadId) + public History MostRecentForDownloadId(string downloadId) { return FindByDownloadId(downloadId) .OrderByDescending(h => h.Date) .FirstOrDefault(); } - public List FindByDownloadId(string downloadId) + public List FindByDownloadId(string downloadId) { return Query(x => x.DownloadId == downloadId); } - public List FindDownloadHistory(int movieId) + public List FindDownloadHistory(int indexerId) { - var allowed = new[] { MovieHistoryEventType.Grabbed, MovieHistoryEventType.DownloadFailed, MovieHistoryEventType.DownloadFolderImported }; + var allowed = new[] { HistoryEventType.ReleaseGrabbed }; - return Query(h => h.MovieId == movieId && + return Query(h => h.IndexerId == indexerId && allowed.Contains(h.EventType)); } - public List GetByMovieId(int movieId, MovieHistoryEventType? eventType) + public List GetByIndexerId(int indexerId, HistoryEventType? eventType) { - var query = Query(x => x.MovieId == movieId); + var query = Query(x => x.IndexerId == indexerId); if (eventType.HasValue) { @@ -56,25 +56,25 @@ namespace NzbDrone.Core.History return query.OrderByDescending(h => h.Date).ToList(); } - public void DeleteForMovies(List movieIds) + public void DeleteForIndexers(List indexerIds) { - Delete(c => movieIds.Contains(c.MovieId)); + Delete(c => indexerIds.Contains(c.IndexerId)); } - public MovieHistory MostRecentForMovie(int movieId) + public History MostRecentForIndexer(int indexerId) { - return Query(x => x.MovieId == movieId) + return Query(x => x.IndexerId == indexerId) .OrderByDescending(h => h.Date) .FirstOrDefault(); } - public List Since(DateTime date, MovieHistoryEventType? eventType) + public List Since(DateTime date, HistoryEventType? eventType) { - var builder = Builder().Where(x => x.Date >= date); + var builder = Builder().Where(x => x.Date >= date); if (eventType.HasValue) { - builder.Where(h => h.EventType == eventType); + builder.Where(h => h.EventType == eventType); } return Query(builder).OrderBy(h => h.Date).ToList(); diff --git a/src/NzbDrone.Core/History/HistoryService.cs b/src/NzbDrone.Core/History/HistoryService.cs index 188ed714e..d5c5eb100 100644 --- a/src/NzbDrone.Core/History/HistoryService.cs +++ b/src/NzbDrone.Core/History/HistoryService.cs @@ -8,15 +8,15 @@ namespace NzbDrone.Core.History { public interface IHistoryService { - PagingSpec Paged(PagingSpec pagingSpec); - MovieHistory MostRecentForMovie(int movieId); - MovieHistory MostRecentForDownloadId(string downloadId); - MovieHistory Get(int historyId); - List Find(string downloadId, MovieHistoryEventType eventType); - List FindByDownloadId(string downloadId); - List GetByMovieId(int movieId, MovieHistoryEventType? eventType); - void UpdateMany(List toUpdate); - List Since(DateTime date, MovieHistoryEventType? eventType); + PagingSpec Paged(PagingSpec pagingSpec); + History MostRecentForIndexer(int indexerId); + History MostRecentForDownloadId(string downloadId); + History Get(int historyId); + List Find(string downloadId, HistoryEventType eventType); + List FindByDownloadId(string downloadId); + List GetByIndexerId(int indexerId, HistoryEventType? eventType); + void UpdateMany(List toUpdate); + List Since(DateTime date, HistoryEventType? eventType); } public class HistoryService : IHistoryService @@ -30,47 +30,47 @@ namespace NzbDrone.Core.History _logger = logger; } - public PagingSpec Paged(PagingSpec pagingSpec) + public PagingSpec Paged(PagingSpec pagingSpec) { return _historyRepository.GetPaged(pagingSpec); } - public MovieHistory MostRecentForMovie(int movieId) + public History MostRecentForIndexer(int indexerId) { - return _historyRepository.MostRecentForMovie(movieId); + return _historyRepository.MostRecentForIndexer(indexerId); } - public MovieHistory MostRecentForDownloadId(string downloadId) + public History MostRecentForDownloadId(string downloadId) { return _historyRepository.MostRecentForDownloadId(downloadId); } - public MovieHistory Get(int historyId) + public History Get(int historyId) { return _historyRepository.Get(historyId); } - public List Find(string downloadId, MovieHistoryEventType eventType) + public List Find(string downloadId, HistoryEventType eventType) { return _historyRepository.FindByDownloadId(downloadId).Where(c => c.EventType == eventType).ToList(); } - public List FindByDownloadId(string downloadId) + public List FindByDownloadId(string downloadId) { return _historyRepository.FindByDownloadId(downloadId); } - public List GetByMovieId(int movieId, MovieHistoryEventType? eventType) + public List GetByIndexerId(int indexerId, HistoryEventType? eventType) { - return _historyRepository.GetByMovieId(movieId, eventType); + return _historyRepository.GetByIndexerId(indexerId, eventType); } - public void UpdateMany(List toUpdate) + public void UpdateMany(List toUpdate) { _historyRepository.UpdateMany(toUpdate); } - public List Since(DateTime date, MovieHistoryEventType? eventType) + public List Since(DateTime date, HistoryEventType? eventType) { return _historyRepository.Since(date, eventType); } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedHistoryItems.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedHistoryItems.cs index 34a8d03a1..ad5a8e8ab 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedHistoryItems.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedHistoryItems.cs @@ -14,19 +14,19 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers public void Clean() { - CleanupOrphanedByMovie(); + CleanupOrphanedByIndexer(); } - private void CleanupOrphanedByMovie() + private void CleanupOrphanedByIndexer() { using (var mapper = _database.OpenConnection()) { mapper.Execute(@"DELETE FROM History WHERE Id IN ( SELECT History.Id FROM History - LEFT OUTER JOIN Movies - ON History.MovieId = Movies.Id - WHERE Movies.Id IS NULL)"); + LEFT OUTER JOIN Indexers + ON History.IndexerId = Indexers.Id + WHERE Indexers.Id IS NULL)"); } } } diff --git a/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs b/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs index b90750b9d..b723c7322 100644 --- a/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs +++ b/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using NLog; +using NzbDrone.Common.Extensions; using NzbDrone.Common.Instrumentation.Extensions; using NzbDrone.Common.TPL; using NzbDrone.Core.Indexers; @@ -56,7 +57,7 @@ namespace NzbDrone.Core.IndexerSearch var reports = new List(); - _logger.ProgressInfo("Searching {0} indexers for {1}", indexers.Count, criteriaBase); + _logger.ProgressInfo("Searching {0} indexers for {1}", indexers.Count, criteriaBase.QueryTitles.Join(", ")); var taskList = new List(); var taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None); diff --git a/src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHD.cs b/src/NzbDrone.Core/Indexers/Definitions/AwesomeHD/AwesomeHD.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHD.cs rename to src/NzbDrone.Core/Indexers/Definitions/AwesomeHD/AwesomeHD.cs diff --git a/src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHDRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Definitions/AwesomeHD/AwesomeHDRequestGenerator.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHDRequestGenerator.cs rename to src/NzbDrone.Core/Indexers/Definitions/AwesomeHD/AwesomeHDRequestGenerator.cs diff --git a/src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHDRssParser.cs b/src/NzbDrone.Core/Indexers/Definitions/AwesomeHD/AwesomeHDRssParser.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHDRssParser.cs rename to src/NzbDrone.Core/Indexers/Definitions/AwesomeHD/AwesomeHDRssParser.cs diff --git a/src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHDSettings.cs b/src/NzbDrone.Core/Indexers/Definitions/AwesomeHD/AwesomeHDSettings.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHDSettings.cs rename to src/NzbDrone.Core/Indexers/Definitions/AwesomeHD/AwesomeHDSettings.cs diff --git a/src/NzbDrone.Core/Indexers/FileList/FileList.cs b/src/NzbDrone.Core/Indexers/Definitions/FileList/FileList.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/FileList/FileList.cs rename to src/NzbDrone.Core/Indexers/Definitions/FileList/FileList.cs diff --git a/src/NzbDrone.Core/Indexers/FileList/FileListApi.cs b/src/NzbDrone.Core/Indexers/Definitions/FileList/FileListApi.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/FileList/FileListApi.cs rename to src/NzbDrone.Core/Indexers/Definitions/FileList/FileListApi.cs diff --git a/src/NzbDrone.Core/Indexers/FileList/FileListParser.cs b/src/NzbDrone.Core/Indexers/Definitions/FileList/FileListParser.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/FileList/FileListParser.cs rename to src/NzbDrone.Core/Indexers/Definitions/FileList/FileListParser.cs diff --git a/src/NzbDrone.Core/Indexers/FileList/FileListRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Definitions/FileList/FileListRequestGenerator.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/FileList/FileListRequestGenerator.cs rename to src/NzbDrone.Core/Indexers/Definitions/FileList/FileListRequestGenerator.cs diff --git a/src/NzbDrone.Core/Indexers/FileList/FileListSettings.cs b/src/NzbDrone.Core/Indexers/Definitions/FileList/FileListSettings.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/FileList/FileListSettings.cs rename to src/NzbDrone.Core/Indexers/Definitions/FileList/FileListSettings.cs diff --git a/src/NzbDrone.Core/Indexers/HDBits/HDBits.cs b/src/NzbDrone.Core/Indexers/Definitions/HDBits/HDBits.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/HDBits/HDBits.cs rename to src/NzbDrone.Core/Indexers/Definitions/HDBits/HDBits.cs diff --git a/src/NzbDrone.Core/Indexers/HDBits/HDBitsApi.cs b/src/NzbDrone.Core/Indexers/Definitions/HDBits/HDBitsApi.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/HDBits/HDBitsApi.cs rename to src/NzbDrone.Core/Indexers/Definitions/HDBits/HDBitsApi.cs diff --git a/src/NzbDrone.Core/Indexers/HDBits/HDBitsInfo.cs b/src/NzbDrone.Core/Indexers/Definitions/HDBits/HDBitsInfo.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/HDBits/HDBitsInfo.cs rename to src/NzbDrone.Core/Indexers/Definitions/HDBits/HDBitsInfo.cs diff --git a/src/NzbDrone.Core/Indexers/HDBits/HDBitsParser.cs b/src/NzbDrone.Core/Indexers/Definitions/HDBits/HDBitsParser.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/HDBits/HDBitsParser.cs rename to src/NzbDrone.Core/Indexers/Definitions/HDBits/HDBitsParser.cs diff --git a/src/NzbDrone.Core/Indexers/HDBits/HDBitsRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Definitions/HDBits/HDBitsRequestGenerator.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/HDBits/HDBitsRequestGenerator.cs rename to src/NzbDrone.Core/Indexers/Definitions/HDBits/HDBitsRequestGenerator.cs diff --git a/src/NzbDrone.Core/Indexers/HDBits/HDBitsSettings.cs b/src/NzbDrone.Core/Indexers/Definitions/HDBits/HDBitsSettings.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/HDBits/HDBitsSettings.cs rename to src/NzbDrone.Core/Indexers/Definitions/HDBits/HDBitsSettings.cs diff --git a/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrents.cs b/src/NzbDrone.Core/Indexers/Definitions/IPTorrents/IPTorrents.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/IPTorrents/IPTorrents.cs rename to src/NzbDrone.Core/Indexers/Definitions/IPTorrents/IPTorrents.cs diff --git a/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrentsRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Definitions/IPTorrents/IPTorrentsRequestGenerator.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/IPTorrents/IPTorrentsRequestGenerator.cs rename to src/NzbDrone.Core/Indexers/Definitions/IPTorrents/IPTorrentsRequestGenerator.cs diff --git a/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrentsSettings.cs b/src/NzbDrone.Core/Indexers/Definitions/IPTorrents/IPTorrentsSettings.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/IPTorrents/IPTorrentsSettings.cs rename to src/NzbDrone.Core/Indexers/Definitions/IPTorrents/IPTorrentsSettings.cs diff --git a/src/NzbDrone.Core/Indexers/Newznab/Newznab.cs b/src/NzbDrone.Core/Indexers/Definitions/Newznab/Newznab.cs similarity index 96% rename from src/NzbDrone.Core/Indexers/Newznab/Newznab.cs rename to src/NzbDrone.Core/Indexers/Definitions/Newznab/Newznab.cs index f9220628e..3cf28551a 100644 --- a/src/NzbDrone.Core/Indexers/Newznab/Newznab.cs +++ b/src/NzbDrone.Core/Indexers/Definitions/Newznab/Newznab.cs @@ -75,11 +75,7 @@ namespace NzbDrone.Core.Indexers.Newznab Protocol = DownloadProtocol.Usenet, Privacy = IndexerPrivacy.Private, SupportsRss = SupportsRss, - SupportsSearch = SupportsSearch, - SupportsBooks = SupportsBooks, - SupportsMovies = SupportsMovies, - SupportsMusic = SupportsMusic, - SupportsTv = SupportsTv + SupportsSearch = SupportsSearch }; } diff --git a/src/NzbDrone.Core/Indexers/Newznab/NewznabCapabilities.cs b/src/NzbDrone.Core/Indexers/Definitions/Newznab/NewznabCapabilities.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Newznab/NewznabCapabilities.cs rename to src/NzbDrone.Core/Indexers/Definitions/Newznab/NewznabCapabilities.cs diff --git a/src/NzbDrone.Core/Indexers/Newznab/NewznabCapabilitiesProvider.cs b/src/NzbDrone.Core/Indexers/Definitions/Newznab/NewznabCapabilitiesProvider.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Newznab/NewznabCapabilitiesProvider.cs rename to src/NzbDrone.Core/Indexers/Definitions/Newznab/NewznabCapabilitiesProvider.cs diff --git a/src/NzbDrone.Core/Indexers/Newznab/NewznabException.cs b/src/NzbDrone.Core/Indexers/Definitions/Newznab/NewznabException.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Newznab/NewznabException.cs rename to src/NzbDrone.Core/Indexers/Definitions/Newznab/NewznabException.cs diff --git a/src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Definitions/Newznab/NewznabRequestGenerator.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs rename to src/NzbDrone.Core/Indexers/Definitions/Newznab/NewznabRequestGenerator.cs diff --git a/src/NzbDrone.Core/Indexers/Newznab/NewznabRssParser.cs b/src/NzbDrone.Core/Indexers/Definitions/Newznab/NewznabRssParser.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Newznab/NewznabRssParser.cs rename to src/NzbDrone.Core/Indexers/Definitions/Newznab/NewznabRssParser.cs diff --git a/src/NzbDrone.Core/Indexers/Newznab/NewznabSettings.cs b/src/NzbDrone.Core/Indexers/Definitions/Newznab/NewznabSettings.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Newznab/NewznabSettings.cs rename to src/NzbDrone.Core/Indexers/Definitions/Newznab/NewznabSettings.cs diff --git a/src/NzbDrone.Core/Indexers/Nyaa/Nyaa.cs b/src/NzbDrone.Core/Indexers/Definitions/Nyaa/Nyaa.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Nyaa/Nyaa.cs rename to src/NzbDrone.Core/Indexers/Definitions/Nyaa/Nyaa.cs diff --git a/src/NzbDrone.Core/Indexers/Nyaa/NyaaRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Definitions/Nyaa/NyaaRequestGenerator.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Nyaa/NyaaRequestGenerator.cs rename to src/NzbDrone.Core/Indexers/Definitions/Nyaa/NyaaRequestGenerator.cs diff --git a/src/NzbDrone.Core/Indexers/Nyaa/NyaaSettings.cs b/src/NzbDrone.Core/Indexers/Definitions/Nyaa/NyaaSettings.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Nyaa/NyaaSettings.cs rename to src/NzbDrone.Core/Indexers/Definitions/Nyaa/NyaaSettings.cs diff --git a/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcorn.cs b/src/NzbDrone.Core/Indexers/Definitions/PassThePopcorn/PassThePopcorn.cs similarity index 82% rename from src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcorn.cs rename to src/NzbDrone.Core/Indexers/Definitions/PassThePopcorn/PassThePopcorn.cs index c4d6bd970..c113aa654 100644 --- a/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcorn.cs +++ b/src/NzbDrone.Core/Indexers/Definitions/PassThePopcorn/PassThePopcorn.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using NLog; using NzbDrone.Common.Cache; using NzbDrone.Common.Http; @@ -12,10 +13,15 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override bool SupportsRss => true; public override bool SupportsSearch => true; - public override bool SupportsMusic => false; - public override bool SupportsTv => false; - public override bool SupportsMovies => true; - public override bool SupportsBooks => false; + + public override IndexerCapabilities Capabilities => new IndexerCapabilities + { + MovieSearchParams = new List + { + MovieSearchParam.Q, MovieSearchParam.ImdbId + } + }; + public override int PageSize => 50; public PassThePopcorn(IHttpClient httpClient, diff --git a/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornApi.cs b/src/NzbDrone.Core/Indexers/Definitions/PassThePopcorn/PassThePopcornApi.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornApi.cs rename to src/NzbDrone.Core/Indexers/Definitions/PassThePopcorn/PassThePopcornApi.cs diff --git a/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornInfo.cs b/src/NzbDrone.Core/Indexers/Definitions/PassThePopcorn/PassThePopcornInfo.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornInfo.cs rename to src/NzbDrone.Core/Indexers/Definitions/PassThePopcorn/PassThePopcornInfo.cs diff --git a/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornParser.cs b/src/NzbDrone.Core/Indexers/Definitions/PassThePopcorn/PassThePopcornParser.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornParser.cs rename to src/NzbDrone.Core/Indexers/Definitions/PassThePopcorn/PassThePopcornParser.cs diff --git a/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Definitions/PassThePopcorn/PassThePopcornRequestGenerator.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornRequestGenerator.cs rename to src/NzbDrone.Core/Indexers/Definitions/PassThePopcorn/PassThePopcornRequestGenerator.cs diff --git a/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornSettings.cs b/src/NzbDrone.Core/Indexers/Definitions/PassThePopcorn/PassThePopcornSettings.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornSettings.cs rename to src/NzbDrone.Core/Indexers/Definitions/PassThePopcorn/PassThePopcornSettings.cs diff --git a/src/NzbDrone.Core/Indexers/Rarbg/Rarbg.cs b/src/NzbDrone.Core/Indexers/Definitions/Rarbg/Rarbg.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Rarbg/Rarbg.cs rename to src/NzbDrone.Core/Indexers/Definitions/Rarbg/Rarbg.cs diff --git a/src/NzbDrone.Core/Indexers/Rarbg/RarbgParser.cs b/src/NzbDrone.Core/Indexers/Definitions/Rarbg/RarbgParser.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Rarbg/RarbgParser.cs rename to src/NzbDrone.Core/Indexers/Definitions/Rarbg/RarbgParser.cs diff --git a/src/NzbDrone.Core/Indexers/Rarbg/RarbgRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Definitions/Rarbg/RarbgRequestGenerator.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Rarbg/RarbgRequestGenerator.cs rename to src/NzbDrone.Core/Indexers/Definitions/Rarbg/RarbgRequestGenerator.cs diff --git a/src/NzbDrone.Core/Indexers/Rarbg/RarbgResponse.cs b/src/NzbDrone.Core/Indexers/Definitions/Rarbg/RarbgResponse.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Rarbg/RarbgResponse.cs rename to src/NzbDrone.Core/Indexers/Definitions/Rarbg/RarbgResponse.cs diff --git a/src/NzbDrone.Core/Indexers/Rarbg/RarbgSettings.cs b/src/NzbDrone.Core/Indexers/Definitions/Rarbg/RarbgSettings.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Rarbg/RarbgSettings.cs rename to src/NzbDrone.Core/Indexers/Definitions/Rarbg/RarbgSettings.cs diff --git a/src/NzbDrone.Core/Indexers/Rarbg/RarbgTokenProvider.cs b/src/NzbDrone.Core/Indexers/Definitions/Rarbg/RarbgTokenProvider.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Rarbg/RarbgTokenProvider.cs rename to src/NzbDrone.Core/Indexers/Definitions/Rarbg/RarbgTokenProvider.cs diff --git a/src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotato.cs b/src/NzbDrone.Core/Indexers/Definitions/TorrentPotato/TorrentPotato.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotato.cs rename to src/NzbDrone.Core/Indexers/Definitions/TorrentPotato/TorrentPotato.cs diff --git a/src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotatoParser.cs b/src/NzbDrone.Core/Indexers/Definitions/TorrentPotato/TorrentPotatoParser.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotatoParser.cs rename to src/NzbDrone.Core/Indexers/Definitions/TorrentPotato/TorrentPotatoParser.cs diff --git a/src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotatoRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Definitions/TorrentPotato/TorrentPotatoRequestGenerator.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotatoRequestGenerator.cs rename to src/NzbDrone.Core/Indexers/Definitions/TorrentPotato/TorrentPotatoRequestGenerator.cs diff --git a/src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotatoResponse.cs b/src/NzbDrone.Core/Indexers/Definitions/TorrentPotato/TorrentPotatoResponse.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotatoResponse.cs rename to src/NzbDrone.Core/Indexers/Definitions/TorrentPotato/TorrentPotatoResponse.cs diff --git a/src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotatoSettings.cs b/src/NzbDrone.Core/Indexers/Definitions/TorrentPotato/TorrentPotatoSettings.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotatoSettings.cs rename to src/NzbDrone.Core/Indexers/Definitions/TorrentPotato/TorrentPotatoSettings.cs diff --git a/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexer.cs b/src/NzbDrone.Core/Indexers/Definitions/TorrentRss/TorrentRssIndexer.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexer.cs rename to src/NzbDrone.Core/Indexers/Definitions/TorrentRss/TorrentRssIndexer.cs diff --git a/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerParserSettings.cs b/src/NzbDrone.Core/Indexers/Definitions/TorrentRss/TorrentRssIndexerParserSettings.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerParserSettings.cs rename to src/NzbDrone.Core/Indexers/Definitions/TorrentRss/TorrentRssIndexerParserSettings.cs diff --git a/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Definitions/TorrentRss/TorrentRssIndexerRequestGenerator.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerRequestGenerator.cs rename to src/NzbDrone.Core/Indexers/Definitions/TorrentRss/TorrentRssIndexerRequestGenerator.cs diff --git a/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerSettings.cs b/src/NzbDrone.Core/Indexers/Definitions/TorrentRss/TorrentRssIndexerSettings.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerSettings.cs rename to src/NzbDrone.Core/Indexers/Definitions/TorrentRss/TorrentRssIndexerSettings.cs diff --git a/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssParserFactory.cs b/src/NzbDrone.Core/Indexers/Definitions/TorrentRss/TorrentRssParserFactory.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssParserFactory.cs rename to src/NzbDrone.Core/Indexers/Definitions/TorrentRss/TorrentRssParserFactory.cs diff --git a/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssSettingsDetector.cs b/src/NzbDrone.Core/Indexers/Definitions/TorrentRss/TorrentRssSettingsDetector.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssSettingsDetector.cs rename to src/NzbDrone.Core/Indexers/Definitions/TorrentRss/TorrentRssSettingsDetector.cs diff --git a/src/NzbDrone.Core/Indexers/Torznab/Torznab.cs b/src/NzbDrone.Core/Indexers/Definitions/Torznab/Torznab.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Torznab/Torznab.cs rename to src/NzbDrone.Core/Indexers/Definitions/Torznab/Torznab.cs diff --git a/src/NzbDrone.Core/Indexers/Torznab/TorznabException.cs b/src/NzbDrone.Core/Indexers/Definitions/Torznab/TorznabException.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Torznab/TorznabException.cs rename to src/NzbDrone.Core/Indexers/Definitions/Torznab/TorznabException.cs diff --git a/src/NzbDrone.Core/Indexers/Torznab/TorznabRssParser.cs b/src/NzbDrone.Core/Indexers/Definitions/Torznab/TorznabRssParser.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Torznab/TorznabRssParser.cs rename to src/NzbDrone.Core/Indexers/Definitions/Torznab/TorznabRssParser.cs diff --git a/src/NzbDrone.Core/Indexers/Torznab/TorznabSettings.cs b/src/NzbDrone.Core/Indexers/Definitions/Torznab/TorznabSettings.cs similarity index 100% rename from src/NzbDrone.Core/Indexers/Torznab/TorznabSettings.cs rename to src/NzbDrone.Core/Indexers/Definitions/Torznab/TorznabSettings.cs diff --git a/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs b/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs index 67ed01e75..2a6a10932 100644 --- a/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs +++ b/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs @@ -23,10 +23,7 @@ namespace NzbDrone.Core.Indexers public override bool SupportsRss => true; public override bool SupportsSearch => true; - public override bool SupportsMusic => true; - public override bool SupportsTv => true; - public override bool SupportsMovies => true; - public override bool SupportsBooks => true; + public override IndexerCapabilities Capabilities => new IndexerCapabilities(); public bool SupportsPaging => PageSize > 0; diff --git a/src/NzbDrone.Core/Indexers/IIndexer.cs b/src/NzbDrone.Core/Indexers/IIndexer.cs index bff0e0f44..a05e42362 100644 --- a/src/NzbDrone.Core/Indexers/IIndexer.cs +++ b/src/NzbDrone.Core/Indexers/IIndexer.cs @@ -9,10 +9,7 @@ namespace NzbDrone.Core.Indexers { bool SupportsRss { get; } bool SupportsSearch { get; } - bool SupportsMusic { get; } - bool SupportsTv { get; } - bool SupportsMovies { get; } - bool SupportsBooks { get; } + IndexerCapabilities Capabilities { get; } DownloadProtocol Protocol { get; } IndexerPrivacy Privacy { get; } diff --git a/src/NzbDrone.Core/Indexers/IndexerBase.cs b/src/NzbDrone.Core/Indexers/IndexerBase.cs index c893e5ec9..160ec444a 100644 --- a/src/NzbDrone.Core/Indexers/IndexerBase.cs +++ b/src/NzbDrone.Core/Indexers/IndexerBase.cs @@ -25,11 +25,7 @@ namespace NzbDrone.Core.Indexers public abstract bool SupportsRss { get; } public abstract bool SupportsSearch { get; } - - public abstract bool SupportsMusic { get; } - public abstract bool SupportsTv { get; } - public abstract bool SupportsMovies { get; } - public abstract bool SupportsBooks { get; } + public abstract IndexerCapabilities Capabilities { get; } public IndexerBase(IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) { diff --git a/src/NzbDrone.Core/Indexers/IndexerCapabilities.cs b/src/NzbDrone.Core/Indexers/IndexerCapabilities.cs new file mode 100644 index 000000000..f7f5144db --- /dev/null +++ b/src/NzbDrone.Core/Indexers/IndexerCapabilities.cs @@ -0,0 +1,308 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; + +namespace NzbDrone.Core.Indexers +{ + public enum TvSearchParam + { + Q, + Season, + Ep, + ImdbId, + TvdbId, + RId, + } + + public enum MovieSearchParam + { + Q, + ImdbId, + TmdbId + } + + public enum MusicSearchParam + { + Q, + Album, + Artist, + Label, + Year + } + + public class IndexerCapabilities + { + public int? LimitsMax { get; set; } + public int? LimitsDefault { get; set; } + + public bool SearchAvailable { get; set; } + + public List TvSearchParams; + public bool TvSearchAvailable => TvSearchParams.Count > 0; + public bool TvSearchSeasonAvailable => TvSearchParams.Contains(TvSearchParam.Season); + public bool TvSearchEpAvailable => TvSearchParams.Contains(TvSearchParam.Ep); + public bool TvSearchImdbAvailable => TvSearchParams.Contains(TvSearchParam.ImdbId); + public bool TvSearchTvdbAvailable => TvSearchParams.Contains(TvSearchParam.TvdbId); + public bool TvSearchTvRageAvailable => TvSearchParams.Contains(TvSearchParam.RId); + + public List MovieSearchParams; + public bool MovieSearchAvailable => MovieSearchParams.Count > 0; + public bool MovieSearchImdbAvailable => MovieSearchParams.Contains(MovieSearchParam.ImdbId); + public bool MovieSearchTmdbAvailable => MovieSearchParams.Contains(MovieSearchParam.TmdbId); + + public List MusicSearchParams; + public bool MusicSearchAvailable => MusicSearchParams.Count > 0; + public bool MusicSearchAlbumAvailable => MusicSearchParams.Contains(MusicSearchParam.Album); + public bool MusicSearchArtistAvailable => MusicSearchParams.Contains(MusicSearchParam.Artist); + public bool MusicSearchLabelAvailable => MusicSearchParams.Contains(MusicSearchParam.Label); + public bool MusicSearchYearAvailable => MusicSearchParams.Contains(MusicSearchParam.Year); + + public bool BookSearchAvailable { get; set; } + + public List Categories { get; private set; } + + public IndexerCapabilities() + { + SearchAvailable = true; + TvSearchParams = new List(); + MovieSearchParams = new List(); + MusicSearchParams = new List(); + BookSearchAvailable = false; + Categories = new List(); + } + + public void ParseTvSearchParams(IEnumerable paramsList) + { + if (paramsList == null) + { + return; + } + + foreach (var paramStr in paramsList) + { + if (Enum.TryParse(paramStr, true, out TvSearchParam param)) + { + if (!TvSearchParams.Contains(param)) + { + TvSearchParams.Add(param); + } + else + { + throw new Exception($"Duplicate tv-search param: {paramStr}"); + } + } + else + { + throw new Exception($"Not supported tv-search param: {paramStr}"); + } + } + } + + public void ParseMovieSearchParams(IEnumerable paramsList) + { + if (paramsList == null) + { + return; + } + + foreach (var paramStr in paramsList) + { + if (Enum.TryParse(paramStr, true, out MovieSearchParam param)) + { + if (!MovieSearchParams.Contains(param)) + { + MovieSearchParams.Add(param); + } + else + { + throw new Exception($"Duplicate movie-search param: {paramStr}"); + } + } + else + { + throw new Exception($"Not supported movie-search param: {paramStr}"); + } + } + } + + public void ParseMusicSearchParams(IEnumerable paramsList) + { + if (paramsList == null) + { + return; + } + + foreach (var paramStr in paramsList) + { + if (Enum.TryParse(paramStr, true, out MusicSearchParam param)) + { + if (!MusicSearchParams.Contains(param)) + { + MusicSearchParams.Add(param); + } + else + { + throw new Exception($"Duplicate music-search param: {paramStr}"); + } + } + else + { + throw new Exception($"Not supported Music-search param: {paramStr}"); + } + } + } + + private string SupportedTvSearchParams() + { + var parameters = new List { "q" }; // q is always enabled + if (TvSearchSeasonAvailable) + { + parameters.Add("season"); + } + + if (TvSearchEpAvailable) + { + parameters.Add("ep"); + } + + if (TvSearchImdbAvailable) + { + parameters.Add("imdbid"); + } + + if (TvSearchTvdbAvailable) + { + parameters.Add("tvdbid"); + } + + if (TvSearchTvRageAvailable) + { + parameters.Add("rid"); + } + + return string.Join(",", parameters); + } + + private string SupportedMovieSearchParams() + { + var parameters = new List { "q" }; // q is always enabled + if (MovieSearchImdbAvailable) + { + parameters.Add("imdbid"); + } + + if (MovieSearchTmdbAvailable) + { + parameters.Add("tmdbid"); + } + + return string.Join(",", parameters); + } + + private string SupportedMusicSearchParams() + { + var parameters = new List { "q" }; // q is always enabled + if (MusicSearchAlbumAvailable) + { + parameters.Add("album"); + } + + if (MusicSearchArtistAvailable) + { + parameters.Add("artist"); + } + + if (MusicSearchLabelAvailable) + { + parameters.Add("label"); + } + + if (MusicSearchYearAvailable) + { + parameters.Add("year"); + } + + return string.Join(",", parameters); + } + + private string SupportedBookSearchParams + { + get + { + var parameters = new List() { "q" }; + if (BookSearchAvailable) + { + parameters.Add("author,title"); + } + + return string.Join(",", parameters); + } + } + + public bool SupportsCategories(int[] categories) + { + var subCategories = Categories.SelectMany(c => c.SubCategories); + var allCategories = Categories.Concat(subCategories); + var supportsCategory = allCategories.Any(i => categories.Any(c => c == i.ID)); + return supportsCategory; + } + + public XDocument GetXDocument() + { + var xdoc = new XDocument( + new XDeclaration("1.0", "UTF-8", null), + new XElement("caps", + new XElement("server", + new XAttribute("title", "Prowlarr")), + LimitsMax != null || LimitsDefault != null ? + new XElement("limits", + LimitsMax != null ? new XAttribute("max", LimitsMax) : null, + LimitsDefault != null ? new XAttribute("default", LimitsDefault) : null) + : null, + new XElement("searching", + new XElement("search", + new XAttribute("available", SearchAvailable ? "yes" : "no"), + new XAttribute("supportedParams", "q")), + new XElement("tv-search", + new XAttribute("available", TvSearchAvailable ? "yes" : "no"), + new XAttribute("supportedParams", SupportedTvSearchParams())), + new XElement("movie-search", + new XAttribute("available", MovieSearchAvailable ? "yes" : "no"), + new XAttribute("supportedParams", SupportedMovieSearchParams())), + new XElement("music-search", + new XAttribute("available", MusicSearchAvailable ? "yes" : "no"), + new XAttribute("supportedParams", SupportedMusicSearchParams())), + new XElement("audio-search", + new XAttribute("available", MusicSearchAvailable ? "yes" : "no"), + new XAttribute("supportedParams", SupportedMusicSearchParams())), + new XElement("book-search", + new XAttribute("available", BookSearchAvailable ? "yes" : "no"), + new XAttribute("supportedParams", SupportedBookSearchParams))), + new XElement("categories", + from c in Categories.OrderBy(x => x.ID < 100000 ? "z" + x.ID.ToString() : x.Name) + select new XElement("category", + new XAttribute("id", c.ID), + new XAttribute("name", c.Name), + from sc in c.SubCategories + select new XElement("subcat", + new XAttribute("id", sc.ID), + new XAttribute("name", sc.Name)))))); + return xdoc; + } + + public string ToXml() => + GetXDocument().Declaration + Environment.NewLine + GetXDocument(); + + public static IndexerCapabilities Concat(IndexerCapabilities left, IndexerCapabilities right) + { + left.SearchAvailable = left.SearchAvailable || right.SearchAvailable; + left.TvSearchParams = left.TvSearchParams.Union(right.TvSearchParams).ToList(); + left.MovieSearchParams = left.MovieSearchParams.Union(right.MovieSearchParams).ToList(); + left.MusicSearchParams = left.MusicSearchParams.Union(right.MusicSearchParams).ToList(); + left.BookSearchAvailable = left.BookSearchAvailable || right.BookSearchAvailable; + left.Categories.AddRange(right.Categories.Where(x => x.ID < 100000).Except(left.Categories)); // exclude indexer specific categories (>= 100000) + return left; + } + } +} diff --git a/src/NzbDrone.Core/Indexers/IndexerCategory.cs b/src/NzbDrone.Core/Indexers/IndexerCategory.cs new file mode 100644 index 000000000..2d4489ab0 --- /dev/null +++ b/src/NzbDrone.Core/Indexers/IndexerCategory.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using Newtonsoft.Json.Linq; + +namespace NzbDrone.Core.Indexers +{ + public class IndexerCategory + { + public int ID { get; set; } + public string Name { get; set; } + + public List SubCategories { get; private set; } + + public IndexerCategory() => SubCategories = new List(); + + public IndexerCategory(int id, string name) + { + ID = id; + Name = name; + SubCategories = new List(); + } + + public bool Contains(IndexerCategory cat) => + Equals(this, cat) || SubCategories.Contains(cat); + + public JToken ToJson() => + new JObject + { + ["ID"] = ID, + ["Name"] = Name + }; + + public override bool Equals(object obj) => (obj as IndexerCategory)?.ID == ID; + + // Get Hash code should be calculated off read only properties. + // ID is not readonly + public override int GetHashCode() => ID; + } +} diff --git a/src/NzbDrone.Core/Indexers/IndexerDefinition.cs b/src/NzbDrone.Core/Indexers/IndexerDefinition.cs index 45ed46f77..33e070d75 100644 --- a/src/NzbDrone.Core/Indexers/IndexerDefinition.cs +++ b/src/NzbDrone.Core/Indexers/IndexerDefinition.cs @@ -12,10 +12,7 @@ namespace NzbDrone.Core.Indexers public IndexerPrivacy Privacy { get; set; } public bool SupportsRss { get; set; } public bool SupportsSearch { get; set; } - public bool SupportsMusic { get; set; } - public bool SupportsTv { get; set; } - public bool SupportsMovies { get; set; } - public bool SupportsBooks { get; set; } + public IndexerCapabilities Capabilities { get; set; } public int Priority { get; set; } = 25; public DateTime Added { get; set; } diff --git a/src/NzbDrone.Core/Indexers/IndexerFactory.cs b/src/NzbDrone.Core/Indexers/IndexerFactory.cs index 2aaee0d6a..2f767f2fb 100644 --- a/src/NzbDrone.Core/Indexers/IndexerFactory.cs +++ b/src/NzbDrone.Core/Indexers/IndexerFactory.cs @@ -45,11 +45,7 @@ namespace NzbDrone.Core.Indexers definition.Protocol = provider.Protocol; definition.Privacy = provider.Privacy; definition.SupportsRss = provider.SupportsRss; - definition.SupportsSearch = provider.SupportsSearch; - definition.SupportsBooks = provider.SupportsBooks; - definition.SupportsMovies = provider.SupportsMovies; - definition.SupportsMusic = provider.SupportsMusic; - definition.SupportsTv = provider.SupportsTv; + definition.Capabilities = provider.Capabilities; } public List RssEnabled(bool filterBlockedIndexers = true) diff --git a/src/Prowlarr.Api.V1/History/HistoryModule.cs b/src/Prowlarr.Api.V1/History/HistoryModule.cs index 27a0d6c31..86f31ef8a 100644 --- a/src/Prowlarr.Api.V1/History/HistoryModule.cs +++ b/src/Prowlarr.Api.V1/History/HistoryModule.cs @@ -23,7 +23,7 @@ namespace Prowlarr.Api.V1.History Get("/movie", x => GetMovieHistory()); } - protected HistoryResource MapToResource(MovieHistory model, bool includeMovie) + protected HistoryResource MapToResource(NzbDrone.Core.History.History model, bool includeMovie) { var resource = model.ToResource(); @@ -32,7 +32,7 @@ namespace Prowlarr.Api.V1.History private PagingResource GetHistory(PagingResource pagingResource) { - var pagingSpec = pagingResource.MapToPagingSpec("date", SortDirection.Descending); + var pagingSpec = pagingResource.MapToPagingSpec("date", SortDirection.Descending); var includeMovie = Request.GetBooleanQueryParameter("includeMovie"); var eventTypeFilter = pagingResource.Filters.FirstOrDefault(f => f.Key == "eventType"); @@ -40,7 +40,7 @@ namespace Prowlarr.Api.V1.History if (eventTypeFilter != null) { - var filterValue = (MovieHistoryEventType)Convert.ToInt32(eventTypeFilter.Value); + var filterValue = (HistoryEventType)Convert.ToInt32(eventTypeFilter.Value); pagingSpec.FilterExpressions.Add(v => v.EventType == filterValue); } @@ -64,12 +64,12 @@ namespace Prowlarr.Api.V1.History } DateTime date = DateTime.Parse(queryDate.Value); - MovieHistoryEventType? eventType = null; + HistoryEventType? eventType = null; var includeMovie = Request.GetBooleanQueryParameter("includeMovie"); if (queryEventType.HasValue) { - eventType = (MovieHistoryEventType)Convert.ToInt32(queryEventType.Value); + eventType = (HistoryEventType)Convert.ToInt32(queryEventType.Value); } return _historyService.Since(date, eventType).Select(h => MapToResource(h, includeMovie)).ToList(); @@ -86,15 +86,15 @@ namespace Prowlarr.Api.V1.History } int movieId = Convert.ToInt32(queryMovieId.Value); - MovieHistoryEventType? eventType = null; + HistoryEventType? eventType = null; var includeMovie = Request.GetBooleanQueryParameter("includeMovie"); if (queryEventType.HasValue) { - eventType = (MovieHistoryEventType)Convert.ToInt32(queryEventType.Value); + eventType = (HistoryEventType)Convert.ToInt32(queryEventType.Value); } - return _historyService.GetByMovieId(movieId, eventType).Select(h => MapToResource(h, includeMovie)).ToList(); + return _historyService.GetByIndexerId(movieId, eventType).Select(h => MapToResource(h, includeMovie)).ToList(); } } } diff --git a/src/Prowlarr.Api.V1/History/HistoryResource.cs b/src/Prowlarr.Api.V1/History/HistoryResource.cs index e2b228ad5..46e8951c0 100644 --- a/src/Prowlarr.Api.V1/History/HistoryResource.cs +++ b/src/Prowlarr.Api.V1/History/HistoryResource.cs @@ -10,19 +10,18 @@ namespace Prowlarr.Api.V1.History { public int MovieId { get; set; } public string SourceTitle { get; set; } - public List Languages { get; set; } public bool QualityCutoffNotMet { get; set; } public DateTime Date { get; set; } public string DownloadId { get; set; } - public MovieHistoryEventType EventType { get; set; } + public HistoryEventType EventType { get; set; } public Dictionary Data { get; set; } } public static class HistoryResourceMapper { - public static HistoryResource ToResource(this MovieHistory model) + public static HistoryResource ToResource(this NzbDrone.Core.History.History model) { if (model == null) { @@ -33,9 +32,8 @@ namespace Prowlarr.Api.V1.History { Id = model.Id, - MovieId = model.MovieId, + MovieId = model.IndexerId, SourceTitle = model.SourceTitle, - Languages = model.Languages, //QualityCutoffNotMet Date = model.Date, diff --git a/src/Prowlarr.Api.V1/Indexers/IndexerModule.cs b/src/Prowlarr.Api.V1/Indexers/IndexerModule.cs index 1b8fa4fd4..ddabb8367 100644 --- a/src/Prowlarr.Api.V1/Indexers/IndexerModule.cs +++ b/src/Prowlarr.Api.V1/Indexers/IndexerModule.cs @@ -1,4 +1,6 @@ +using Nancy; using NzbDrone.Core.Indexers; +using Prowlarr.Http.REST; namespace Prowlarr.Api.V1.Indexers { @@ -6,9 +8,14 @@ namespace Prowlarr.Api.V1.Indexers { public static readonly IndexerResourceMapper ResourceMapper = new IndexerResourceMapper(); + private IIndexerFactory _indexerFactory { get; set; } + public IndexerModule(IndexerFactory indexerFactory) : base(indexerFactory, "indexer", ResourceMapper) { + _indexerFactory = indexerFactory; + + Get("{id}/newznab", x => GetNewznabResponse(x.id)); } protected override void Validate(IndexerDefinition definition, bool includeWarnings) @@ -20,5 +27,27 @@ namespace Prowlarr.Api.V1.Indexers base.Validate(definition, includeWarnings); } + + private object GetNewznabResponse(int id) + { + var requestType = Request.Query.t; + + if (!requestType.HasValue) + { + throw new BadRequestException("Missing Function Parameter"); + } + + if (requestType.Value == "caps") + { + var indexer = _indexerFactory.GetInstance(_indexerFactory.Get(id)); + Response response = indexer.Capabilities.ToXml(); + response.ContentType = "application/rss+xml"; + return response; + } + else + { + throw new BadRequestException("Function Not Available"); + } + } } } diff --git a/src/Prowlarr.Api.V1/Indexers/IndexerResource.cs b/src/Prowlarr.Api.V1/Indexers/IndexerResource.cs index 7a3a7cd20..3601a0917 100644 --- a/src/Prowlarr.Api.V1/Indexers/IndexerResource.cs +++ b/src/Prowlarr.Api.V1/Indexers/IndexerResource.cs @@ -16,6 +16,7 @@ namespace Prowlarr.Api.V1.Indexers public bool SupportsBooks { get; set; } public DownloadProtocol Protocol { get; set; } public IndexerPrivacy Privacy { get; set; } + public IndexerCapabilities Capabilities { get; set; } public int Priority { get; set; } public DateTime Added { get; set; } } @@ -36,10 +37,7 @@ namespace Prowlarr.Api.V1.Indexers resource.EnableInteractiveSearch = definition.EnableInteractiveSearch; resource.SupportsRss = definition.SupportsRss; resource.SupportsSearch = definition.SupportsSearch; - resource.SupportsBooks = definition.SupportsBooks; - resource.SupportsMovies = definition.SupportsMovies; - resource.SupportsMusic = definition.SupportsMusic; - resource.SupportsTv = definition.SupportsTv; + resource.Capabilities = definition.Capabilities; resource.Protocol = definition.Protocol; resource.Privacy = definition.Privacy; resource.Priority = definition.Priority; diff --git a/src/Prowlarr.Api.V1/ProviderModuleBase.cs b/src/Prowlarr.Api.V1/ProviderModuleBase.cs index 4150833ff..33fdabd23 100644 --- a/src/Prowlarr.Api.V1/ProviderModuleBase.cs +++ b/src/Prowlarr.Api.V1/ProviderModuleBase.cs @@ -16,7 +16,7 @@ namespace Prowlarr.Api.V1 where TProvider : IProvider where TProviderResource : ProviderResource, new() { - private readonly IProviderFactory _providerFactory; + protected readonly IProviderFactory _providerFactory; private readonly ProviderResourceMapper _resourceMapper; protected ProviderModuleBase(IProviderFactory providerFactory, string resource, ProviderResourceMapper resourceMapper)