mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2026-04-17 21:44:48 -04:00
Compare commits
36 Commits
http2
...
v0.2.0.144
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc1e397ce3 | ||
|
|
17608cf915 | ||
|
|
a3de574de5 | ||
|
|
22161e6d57 | ||
|
|
c46ed33544 | ||
|
|
7388655e6d | ||
|
|
5b5c186d0c | ||
|
|
ae5d93d6dd | ||
|
|
62f6670a21 | ||
|
|
c9951e7eba | ||
|
|
2da22c08b0 | ||
|
|
e480f53f7f | ||
|
|
8701e67b1e | ||
|
|
97f4a2e651 | ||
|
|
3c3272cb25 | ||
|
|
fa626a53e6 | ||
|
|
76daee3a1b | ||
|
|
1cbf61f4db | ||
|
|
34e57f27ff | ||
|
|
de17ae9969 | ||
|
|
06913a2975 | ||
|
|
dad16f2c57 | ||
|
|
2f22e7295c | ||
|
|
6880f38635 | ||
|
|
a7b1ef19f5 | ||
|
|
aa59da2f22 | ||
|
|
a62a4360e3 | ||
|
|
9e9e666204 | ||
|
|
8d23cbf52b | ||
|
|
d925b37066 | ||
|
|
9dadb35b98 | ||
|
|
79e3e31028 | ||
|
|
0af8e84d2d | ||
|
|
573dde97e5 | ||
|
|
08d112a96f | ||
|
|
76b6b0dead |
@@ -7,7 +7,7 @@ variables:
|
|||||||
outputFolder: './_output'
|
outputFolder: './_output'
|
||||||
artifactsFolder: './_artifacts'
|
artifactsFolder: './_artifacts'
|
||||||
testsFolder: './_tests'
|
testsFolder: './_tests'
|
||||||
majorVersion: '0.1.10'
|
majorVersion: '0.2.0'
|
||||||
minorVersion: $[counter('minorVersion', 1)]
|
minorVersion: $[counter('minorVersion', 1)]
|
||||||
prowlarrVersion: '$(majorVersion).$(minorVersion)'
|
prowlarrVersion: '$(majorVersion).$(minorVersion)'
|
||||||
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'
|
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import BoolFilterBuilderRowValue from './BoolFilterBuilderRowValue';
|
|||||||
import DateFilterBuilderRowValue from './DateFilterBuilderRowValue';
|
import DateFilterBuilderRowValue from './DateFilterBuilderRowValue';
|
||||||
import FilterBuilderRowValueConnector from './FilterBuilderRowValueConnector';
|
import FilterBuilderRowValueConnector from './FilterBuilderRowValueConnector';
|
||||||
import IndexerFilterBuilderRowValueConnector from './IndexerFilterBuilderRowValueConnector';
|
import IndexerFilterBuilderRowValueConnector from './IndexerFilterBuilderRowValueConnector';
|
||||||
|
import PrivacyFilterBuilderRowValue from './PrivacyFilterBuilderRowValue';
|
||||||
import ProtocolFilterBuilderRowValue from './ProtocolFilterBuilderRowValue';
|
import ProtocolFilterBuilderRowValue from './ProtocolFilterBuilderRowValue';
|
||||||
import TagFilterBuilderRowValueConnector from './TagFilterBuilderRowValueConnector';
|
import TagFilterBuilderRowValueConnector from './TagFilterBuilderRowValueConnector';
|
||||||
import styles from './FilterBuilderRow.css';
|
import styles from './FilterBuilderRow.css';
|
||||||
@@ -63,6 +64,9 @@ function getRowValueConnector(selectedFilterBuilderProp) {
|
|||||||
case filterBuilderValueTypes.PROTOCOL:
|
case filterBuilderValueTypes.PROTOCOL:
|
||||||
return ProtocolFilterBuilderRowValue;
|
return ProtocolFilterBuilderRowValue;
|
||||||
|
|
||||||
|
case filterBuilderValueTypes.PRIVACY:
|
||||||
|
return PrivacyFilterBuilderRowValue;
|
||||||
|
|
||||||
case filterBuilderValueTypes.TAG:
|
case filterBuilderValueTypes.TAG:
|
||||||
return TagFilterBuilderRowValueConnector;
|
return TagFilterBuilderRowValueConnector;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
|
import FilterBuilderRowValue from './FilterBuilderRowValue';
|
||||||
|
|
||||||
|
const privacyTypes = [
|
||||||
|
{ id: 'public', name: translate('Public') },
|
||||||
|
{ id: 'private', name: translate('Private') },
|
||||||
|
{ id: 'semiPrivate', name: translate('SemiPrivate') }
|
||||||
|
];
|
||||||
|
|
||||||
|
function PrivacyFilterBuilderRowValue(props) {
|
||||||
|
return (
|
||||||
|
<FilterBuilderRowValue
|
||||||
|
tagList={privacyTypes}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PrivacyFilterBuilderRowValue;
|
||||||
@@ -4,6 +4,7 @@ export const DATE = 'date';
|
|||||||
export const DEFAULT = 'default';
|
export const DEFAULT = 'default';
|
||||||
export const INDEXER = 'indexer';
|
export const INDEXER = 'indexer';
|
||||||
export const PROTOCOL = 'protocol';
|
export const PROTOCOL = 'protocol';
|
||||||
|
export const PRIVACY = 'privacy';
|
||||||
export const APP_PROFILE = 'appProfile';
|
export const APP_PROFILE = 'appProfile';
|
||||||
export const MOVIE_STATUS = 'movieStatus';
|
export const MOVIE_STATUS = 'movieStatus';
|
||||||
export const TAG = 'tag';
|
export const TAG = 'tag';
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Modal from 'Components/Modal/Modal';
|
|||||||
import AddIndexerModalContentConnector from './AddIndexerModalContentConnector';
|
import AddIndexerModalContentConnector from './AddIndexerModalContentConnector';
|
||||||
import styles from './AddIndexerModal.css';
|
import styles from './AddIndexerModal.css';
|
||||||
|
|
||||||
function AddIndexerModal({ isOpen, onModalClose, ...otherProps }) {
|
function AddIndexerModal({ isOpen, onModalClose, onSelectIndexer, ...otherProps }) {
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
@@ -14,6 +14,7 @@ function AddIndexerModal({ isOpen, onModalClose, ...otherProps }) {
|
|||||||
<AddIndexerModalContentConnector
|
<AddIndexerModalContentConnector
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
onModalClose={onModalClose}
|
onModalClose={onModalClose}
|
||||||
|
onSelectIndexer={onSelectIndexer}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
@@ -21,7 +22,8 @@ function AddIndexerModal({ isOpen, onModalClose, ...otherProps }) {
|
|||||||
|
|
||||||
AddIndexerModal.propTypes = {
|
AddIndexerModal.propTypes = {
|
||||||
isOpen: PropTypes.bool.isRequired,
|
isOpen: PropTypes.bool.isRequired,
|
||||||
onModalClose: PropTypes.func.isRequired
|
onModalClose: PropTypes.func.isRequired,
|
||||||
|
onSelectIndexer: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AddIndexerModal;
|
export default AddIndexerModal;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import TableBody from 'Components/Table/TableBody';
|
|||||||
import { kinds, scrollDirections } from 'Helpers/Props';
|
import { kinds, scrollDirections } from 'Helpers/Props';
|
||||||
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
import SelectIndexerRow from './SelectIndexerRow';
|
import SelectIndexerRowConnector from './SelectIndexerRowConnector';
|
||||||
import styles from './AddIndexerModalContent.css';
|
import styles from './AddIndexerModalContent.css';
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
@@ -219,7 +219,7 @@ class AddIndexerModalContent extends Component {
|
|||||||
<TableBody>
|
<TableBody>
|
||||||
{
|
{
|
||||||
filteredIndexers.map((indexer) => (
|
filteredIndexers.map((indexer) => (
|
||||||
<SelectIndexerRow
|
<SelectIndexerRowConnector
|
||||||
key={indexer.name}
|
key={indexer.name}
|
||||||
implementation={indexer.implementation}
|
implementation={indexer.implementation}
|
||||||
{...indexer}
|
{...indexer}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class AddIndexerModalContentConnector extends Component {
|
|||||||
|
|
||||||
onIndexerSelect = ({ implementation, name }) => {
|
onIndexerSelect = ({ implementation, name }) => {
|
||||||
this.props.selectIndexerSchema({ implementation, name });
|
this.props.selectIndexerSchema({ implementation, name });
|
||||||
this.props.onModalClose({ indexerSelected: true });
|
this.props.onSelectIndexer();
|
||||||
};
|
};
|
||||||
|
|
||||||
onSortPress = (sortKey, sortDirection) => {
|
onSortPress = (sortKey, sortDirection) => {
|
||||||
@@ -76,7 +76,8 @@ AddIndexerModalContentConnector.propTypes = {
|
|||||||
fetchIndexerSchema: PropTypes.func.isRequired,
|
fetchIndexerSchema: PropTypes.func.isRequired,
|
||||||
selectIndexerSchema: PropTypes.func.isRequired,
|
selectIndexerSchema: PropTypes.func.isRequired,
|
||||||
setIndexerSchemaSort: PropTypes.func.isRequired,
|
setIndexerSchemaSort: PropTypes.func.isRequired,
|
||||||
onModalClose: PropTypes.func.isRequired
|
onModalClose: PropTypes.func.isRequired,
|
||||||
|
onSelectIndexer: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(createMapStateToProps, mapDispatchToProps)(AddIndexerModalContentConnector);
|
export default connect(createMapStateToProps, mapDispatchToProps)(AddIndexerModalContentConnector);
|
||||||
|
|||||||
@@ -3,3 +3,9 @@
|
|||||||
|
|
||||||
width: 32px;
|
width: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alreadyExistsIcon {
|
||||||
|
margin-left: 10px;
|
||||||
|
color: #37bc9b;
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import Icon from 'Components/Icon';
|
||||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||||
import TableRowButton from 'Components/Table/TableRowButton';
|
import TableRowButton from 'Components/Table/TableRowButton';
|
||||||
|
import { icons } from 'Helpers/Props';
|
||||||
import ProtocolLabel from 'Indexer/Index/Table/ProtocolLabel';
|
import ProtocolLabel from 'Indexer/Index/Table/ProtocolLabel';
|
||||||
import firstCharToUpper from 'Utilities/String/firstCharToUpper';
|
import firstCharToUpper from 'Utilities/String/firstCharToUpper';
|
||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
@@ -29,7 +31,8 @@ class SelectIndexerRow extends Component {
|
|||||||
protocol,
|
protocol,
|
||||||
privacy,
|
privacy,
|
||||||
name,
|
name,
|
||||||
language
|
language,
|
||||||
|
isExistingIndexer
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -42,6 +45,16 @@ class SelectIndexerRow extends Component {
|
|||||||
|
|
||||||
<TableRowCell>
|
<TableRowCell>
|
||||||
{name}
|
{name}
|
||||||
|
{
|
||||||
|
isExistingIndexer ?
|
||||||
|
<Icon
|
||||||
|
className={styles.alreadyExistsIcon}
|
||||||
|
name={icons.CHECK_CIRCLE}
|
||||||
|
size={15}
|
||||||
|
title={translate('IndexerAlreadySetup')}
|
||||||
|
/> :
|
||||||
|
null
|
||||||
|
}
|
||||||
</TableRowCell>
|
</TableRowCell>
|
||||||
|
|
||||||
<TableRowCell>
|
<TableRowCell>
|
||||||
@@ -62,7 +75,8 @@ SelectIndexerRow.propTypes = {
|
|||||||
privacy: PropTypes.string.isRequired,
|
privacy: PropTypes.string.isRequired,
|
||||||
language: PropTypes.string.isRequired,
|
language: PropTypes.string.isRequired,
|
||||||
implementation: PropTypes.string.isRequired,
|
implementation: PropTypes.string.isRequired,
|
||||||
onIndexerSelect: PropTypes.func.isRequired
|
onIndexerSelect: PropTypes.func.isRequired,
|
||||||
|
isExistingIndexer: PropTypes.bool.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SelectIndexerRow;
|
export default SelectIndexerRow;
|
||||||
|
|||||||
18
frontend/src/Indexer/Add/SelectIndexerRowConnector.js
Normal file
18
frontend/src/Indexer/Add/SelectIndexerRowConnector.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
import createExistingIndexerSelector from 'Store/Selectors/createExistingIndexerSelector';
|
||||||
|
import SelectIndexerRow from './SelectIndexerRow';
|
||||||
|
|
||||||
|
function createMapStateToProps() {
|
||||||
|
return createSelector(
|
||||||
|
createExistingIndexerSelector(),
|
||||||
|
(isExistingIndexer, dimensions) => {
|
||||||
|
return {
|
||||||
|
isExistingIndexer
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(createMapStateToProps)(SelectIndexerRow);
|
||||||
@@ -39,6 +39,7 @@ function EditIndexerModalContent(props) {
|
|||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
implementationName,
|
implementationName,
|
||||||
|
definitionName,
|
||||||
name,
|
name,
|
||||||
enable,
|
enable,
|
||||||
redirect,
|
redirect,
|
||||||
@@ -50,10 +51,12 @@ function EditIndexerModalContent(props) {
|
|||||||
priority
|
priority
|
||||||
} = item;
|
} = item;
|
||||||
|
|
||||||
|
const indexerDisplayName = implementationName === definitionName ? implementationName : `${implementationName} (${definitionName})`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalContent onModalClose={onModalClose}>
|
<ModalContent onModalClose={onModalClose}>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
{`${id ? translate('EditIndexer') : translate('AddIndexer')} - ${implementationName}`}
|
{`${id ? translate('EditIndexer') : translate('AddIndexer')} - ${indexerDisplayName}`}
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
|
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
|
|||||||
@@ -193,11 +193,12 @@ class IndexerIndex extends Component {
|
|||||||
this.setState({ isAddIndexerModalOpen: true });
|
this.setState({ isAddIndexerModalOpen: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
onAddIndexerModalClose = ({ indexerSelected = false } = {}) => {
|
onAddIndexerModalClose = () => {
|
||||||
this.setState({
|
this.setState({ isAddIndexerModalOpen: false });
|
||||||
isAddIndexerModalOpen: false,
|
};
|
||||||
isEditIndexerModalOpen: indexerSelected
|
|
||||||
});
|
onAddIndexerSelectIndexer = () => {
|
||||||
|
this.setState({ isEditIndexerModalOpen: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
onEditIndexerModalClose = () => {
|
onEditIndexerModalClose = () => {
|
||||||
@@ -463,6 +464,7 @@ class IndexerIndex extends Component {
|
|||||||
<AddIndexerModal
|
<AddIndexerModal
|
||||||
isOpen={isAddIndexerModalOpen}
|
isOpen={isAddIndexerModalOpen}
|
||||||
onModalClose={this.onAddIndexerModalClose}
|
onModalClose={this.onAddIndexerModalClose}
|
||||||
|
onSelectIndexer={this.onAddIndexerSelectIndexer}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<EditIndexerModalConnector
|
<EditIndexerModalConnector
|
||||||
|
|||||||
@@ -244,12 +244,15 @@ class IndexerIndexRow extends Component {
|
|||||||
onPress={this.onIndexerInfoPress}
|
onPress={this.onIndexerInfoPress}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<IconButton
|
{
|
||||||
className={styles.externalLink}
|
indexerUrls ?
|
||||||
name={icons.EXTERNAL_LINK}
|
<IconButton
|
||||||
title={translate('Website')}
|
className={styles.externalLink}
|
||||||
to={indexerUrls[0].replace('api.', '')}
|
name={icons.EXTERNAL_LINK}
|
||||||
/>
|
title={translate('Website')}
|
||||||
|
to={indexerUrls[0].replace('api.', '')}
|
||||||
|
/> : null
|
||||||
|
}
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
name={icons.EDIT}
|
name={icons.EDIT}
|
||||||
@@ -289,7 +292,7 @@ class IndexerIndexRow extends Component {
|
|||||||
|
|
||||||
IndexerIndexRow.propTypes = {
|
IndexerIndexRow.propTypes = {
|
||||||
id: PropTypes.number.isRequired,
|
id: PropTypes.number.isRequired,
|
||||||
indexerUrls: PropTypes.arrayOf(PropTypes.string).isRequired,
|
indexerUrls: PropTypes.arrayOf(PropTypes.string),
|
||||||
protocol: PropTypes.string.isRequired,
|
protocol: PropTypes.string.isRequired,
|
||||||
privacy: PropTypes.string.isRequired,
|
privacy: PropTypes.string.isRequired,
|
||||||
priority: PropTypes.number.isRequired,
|
priority: PropTypes.number.isRequired,
|
||||||
@@ -298,7 +301,7 @@ IndexerIndexRow.propTypes = {
|
|||||||
redirect: PropTypes.bool.isRequired,
|
redirect: PropTypes.bool.isRequired,
|
||||||
appProfile: PropTypes.object.isRequired,
|
appProfile: PropTypes.object.isRequired,
|
||||||
status: PropTypes.object,
|
status: PropTypes.object,
|
||||||
capabilities: PropTypes.object.isRequired,
|
capabilities: PropTypes.object,
|
||||||
added: PropTypes.string.isRequired,
|
added: PropTypes.string.isRequired,
|
||||||
tags: PropTypes.arrayOf(PropTypes.number).isRequired,
|
tags: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
|||||||
@@ -118,12 +118,12 @@ export const defaultState = {
|
|||||||
filterBuilderProps: [
|
filterBuilderProps: [
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: 'Indexer Name',
|
label: translate('IndexerName'),
|
||||||
type: filterBuilderTypes.STRING
|
type: filterBuilderTypes.STRING
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'enable',
|
name: 'enable',
|
||||||
label: 'Enabled',
|
label: translate('Enabled'),
|
||||||
type: filterBuilderTypes.EXACT,
|
type: filterBuilderTypes.EXACT,
|
||||||
valueType: filterBuilderValueTypes.BOOL
|
valueType: filterBuilderValueTypes.BOOL
|
||||||
},
|
},
|
||||||
@@ -135,15 +135,21 @@ export const defaultState = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'priority',
|
name: 'priority',
|
||||||
label: 'Priority',
|
label: translate('Priority'),
|
||||||
type: filterBuilderTypes.NUMBER
|
type: filterBuilderTypes.NUMBER
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'protocol',
|
name: 'protocol',
|
||||||
label: 'Protocol',
|
label: translate('Protocol'),
|
||||||
type: filterBuilderTypes.EXACT,
|
type: filterBuilderTypes.EXACT,
|
||||||
valueType: filterBuilderValueTypes.PROTOCOL
|
valueType: filterBuilderValueTypes.PROTOCOL
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'privacy',
|
||||||
|
label: translate('Privacy'),
|
||||||
|
type: filterBuilderTypes.EXACT,
|
||||||
|
valueType: filterBuilderValueTypes.PRIVACY
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'appProfileId',
|
name: 'appProfileId',
|
||||||
label: translate('AppProfile'),
|
label: translate('AppProfile'),
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ export default function createSentryMiddleware() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dsn = isProduction ? 'https://b0fb75c38ef4487dbf742f79c4ba62d2@sentry.servarr.com/12' :
|
const dsn = isProduction ? 'https://b233094711fe4430a0b0c5da2e01df93@sentry.servarr.com/28' :
|
||||||
'https://da610619280249f891ec3ee306906793@sentry.servarr.com/13';
|
'https://116efebd253a4dff9df9475a31510001@sentry.servarr.com/37';
|
||||||
|
|
||||||
sentry.init({
|
sentry.init({
|
||||||
dsn,
|
dsn,
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
import _ from 'lodash';
|
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
function createExclusionMovieSelector() {
|
|
||||||
return createSelector(
|
|
||||||
(state, { tmdbId }) => tmdbId,
|
|
||||||
(state) => state.settings.importExclusions,
|
|
||||||
(tmdbId, importExclusions) => {
|
|
||||||
return _.some(importExclusions.items, { tmdbId });
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default createExclusionMovieSelector;
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
import createAllIndexersSelector from './createAllIndexersSelector';
|
||||||
|
|
||||||
|
function createExistingIndexerSelector() {
|
||||||
|
return createSelector(
|
||||||
|
(state, { definitionName }) => definitionName,
|
||||||
|
createAllIndexersSelector(),
|
||||||
|
(definitionName, indexers) => {
|
||||||
|
return _.some(indexers, { definitionName });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default createExistingIndexerSelector;
|
||||||
@@ -36,6 +36,12 @@ function selectSettings(item, pendingChanges, saveError) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key === 'definitionName') {
|
||||||
|
result.definitionName = item[key];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
const setting = {
|
const setting = {
|
||||||
value: item[key],
|
value: item[key],
|
||||||
errors: _.map(_.remove(validationFailures, (failure) => {
|
errors: _.map(_.remove(validationFailures, (failure) => {
|
||||||
|
|||||||
@@ -82,9 +82,6 @@ namespace NzbDrone.Common.Http.Dispatchers
|
|||||||
|
|
||||||
if (httpWebResponse == null)
|
if (httpWebResponse == null)
|
||||||
{
|
{
|
||||||
// Workaround for mono not closing connections properly in certain situations.
|
|
||||||
AbortWebRequest(webRequest);
|
|
||||||
|
|
||||||
// The default messages for WebException on mono are pretty horrible.
|
// The default messages for WebException on mono are pretty horrible.
|
||||||
if (e.Status == WebExceptionStatus.NameResolutionFailure)
|
if (e.Status == WebExceptionStatus.NameResolutionFailure)
|
||||||
{
|
{
|
||||||
@@ -242,36 +239,5 @@ namespace NzbDrone.Common.Http.Dispatchers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workaround for mono not closing connections properly on timeouts
|
|
||||||
private void AbortWebRequest(HttpWebRequest webRequest)
|
|
||||||
{
|
|
||||||
// First affected version was mono 5.16
|
|
||||||
if (OsInfo.IsNotWindows && _platformInfo.Version >= new Version(5, 16))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var currentOperationInfo = webRequest.GetType().GetField("currentOperation", BindingFlags.NonPublic | BindingFlags.Instance);
|
|
||||||
var currentOperation = currentOperationInfo.GetValue(webRequest);
|
|
||||||
|
|
||||||
if (currentOperation != null)
|
|
||||||
{
|
|
||||||
var responseStreamInfo = currentOperation.GetType().GetField("responseStream", BindingFlags.NonPublic | BindingFlags.Instance);
|
|
||||||
var responseStream = responseStreamInfo.GetValue(currentOperation) as Stream;
|
|
||||||
|
|
||||||
// Note that responseStream will likely be null once mono fixes it.
|
|
||||||
responseStream?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// This can fail randomly on future mono versions that have been changed/fixed. Log to sentry and ignore.
|
|
||||||
_logger.Trace()
|
|
||||||
.Exception(ex)
|
|
||||||
.Message("Unable to dispose responseStream on mono {0}", _platformInfo.Version)
|
|
||||||
.Write();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Cache;
|
using NzbDrone.Common.Cache;
|
||||||
@@ -87,7 +88,7 @@ namespace NzbDrone.Common.Http
|
|||||||
// 302 or 303 should default to GET on redirect even if POST on original
|
// 302 or 303 should default to GET on redirect even if POST on original
|
||||||
if (response.StatusCode == HttpStatusCode.Redirect || response.StatusCode == HttpStatusCode.RedirectMethod)
|
if (response.StatusCode == HttpStatusCode.Redirect || response.StatusCode == HttpStatusCode.RedirectMethod)
|
||||||
{
|
{
|
||||||
request.Method = HttpMethod.GET;
|
request.Method = HttpMethod.Get;
|
||||||
request.ContentData = null;
|
request.ContentData = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +264,7 @@ namespace NzbDrone.Common.Http
|
|||||||
|
|
||||||
public Task<HttpResponse> GetAsync(HttpRequest request)
|
public Task<HttpResponse> GetAsync(HttpRequest request)
|
||||||
{
|
{
|
||||||
request.Method = HttpMethod.GET;
|
request.Method = HttpMethod.Get;
|
||||||
return ExecuteAsync(request);
|
return ExecuteAsync(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,7 +289,7 @@ namespace NzbDrone.Common.Http
|
|||||||
|
|
||||||
public Task<HttpResponse> HeadAsync(HttpRequest request)
|
public Task<HttpResponse> HeadAsync(HttpRequest request)
|
||||||
{
|
{
|
||||||
request.Method = HttpMethod.HEAD;
|
request.Method = HttpMethod.Head;
|
||||||
return ExecuteAsync(request);
|
return ExecuteAsync(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +300,7 @@ namespace NzbDrone.Common.Http
|
|||||||
|
|
||||||
public Task<HttpResponse> PostAsync(HttpRequest request)
|
public Task<HttpResponse> PostAsync(HttpRequest request)
|
||||||
{
|
{
|
||||||
request.Method = HttpMethod.POST;
|
request.Method = HttpMethod.Post;
|
||||||
return ExecuteAsync(request);
|
return ExecuteAsync(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
namespace NzbDrone.Common.Http
|
|
||||||
{
|
|
||||||
public enum HttpMethod
|
|
||||||
{
|
|
||||||
GET,
|
|
||||||
POST,
|
|
||||||
PUT,
|
|
||||||
DELETE,
|
|
||||||
HEAD,
|
|
||||||
OPTIONS,
|
|
||||||
PATCH,
|
|
||||||
MERGE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
@@ -13,6 +14,7 @@ namespace NzbDrone.Common.Http
|
|||||||
{
|
{
|
||||||
Url = new HttpUri(url);
|
Url = new HttpUri(url);
|
||||||
Headers = new HttpHeader();
|
Headers = new HttpHeader();
|
||||||
|
Method = HttpMethod.Get;
|
||||||
ConnectionKeepAlive = true;
|
ConnectionKeepAlive = true;
|
||||||
AllowAutoRedirect = true;
|
AllowAutoRedirect = true;
|
||||||
Cookies = new Dictionary<string, string>();
|
Cookies = new Dictionary<string, string>();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ namespace NzbDrone.Common.Http
|
|||||||
{
|
{
|
||||||
BaseUrl = new HttpUri(baseUrl);
|
BaseUrl = new HttpUri(baseUrl);
|
||||||
ResourceUrl = string.Empty;
|
ResourceUrl = string.Empty;
|
||||||
Method = HttpMethod.GET;
|
Method = HttpMethod.Get;
|
||||||
Encoding = Encoding.UTF8;
|
Encoding = Encoding.UTF8;
|
||||||
QueryParams = new List<KeyValuePair<string, string>>();
|
QueryParams = new List<KeyValuePair<string, string>>();
|
||||||
SuffixQueryParams = new List<KeyValuePair<string, string>>();
|
SuffixQueryParams = new List<KeyValuePair<string, string>>();
|
||||||
@@ -275,7 +276,7 @@ namespace NzbDrone.Common.Http
|
|||||||
|
|
||||||
public virtual HttpRequestBuilder Post()
|
public virtual HttpRequestBuilder Post()
|
||||||
{
|
{
|
||||||
Method = HttpMethod.POST;
|
Method = HttpMethod.Post;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -397,7 +398,7 @@ namespace NzbDrone.Common.Http
|
|||||||
|
|
||||||
public virtual HttpRequestBuilder AddFormParameter(string key, object value)
|
public virtual HttpRequestBuilder AddFormParameter(string key, object value)
|
||||||
{
|
{
|
||||||
if (Method != HttpMethod.POST)
|
if (Method != HttpMethod.Post)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException("HttpRequest Method must be POST to add FormParameter.");
|
throw new NotSupportedException("HttpRequest Method must be POST to add FormParameter.");
|
||||||
}
|
}
|
||||||
@@ -413,7 +414,7 @@ namespace NzbDrone.Common.Http
|
|||||||
|
|
||||||
public virtual HttpRequestBuilder AddFormUpload(string name, string fileName, byte[] data, string contentType = "application/octet-stream")
|
public virtual HttpRequestBuilder AddFormUpload(string name, string fileName, byte[] data, string contentType = "application/octet-stream")
|
||||||
{
|
{
|
||||||
if (Method != HttpMethod.POST)
|
if (Method != HttpMethod.Post)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException("HttpRequest Method must be POST to add FormUpload.");
|
throw new NotSupportedException("HttpRequest Method must be POST to add FormUpload.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
|
|
||||||
@@ -17,14 +18,14 @@ namespace NzbDrone.Common.Http
|
|||||||
public JsonRpcRequestBuilder(string baseUrl)
|
public JsonRpcRequestBuilder(string baseUrl)
|
||||||
: base(baseUrl)
|
: base(baseUrl)
|
||||||
{
|
{
|
||||||
Method = HttpMethod.POST;
|
Method = HttpMethod.Post;
|
||||||
JsonParameters = new List<object>();
|
JsonParameters = new List<object>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonRpcRequestBuilder(string baseUrl, string method, IEnumerable<object> parameters)
|
public JsonRpcRequestBuilder(string baseUrl, string method, IEnumerable<object> parameters)
|
||||||
: base(baseUrl)
|
: base(baseUrl)
|
||||||
{
|
{
|
||||||
Method = HttpMethod.POST;
|
Method = HttpMethod.Post;
|
||||||
JsonMethod = method;
|
JsonMethod = method;
|
||||||
JsonParameters = parameters.ToList();
|
JsonParameters = parameters.ToList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
@@ -34,7 +35,7 @@ namespace NzbDrone.Core.Test.IndexerTests.AvistazTests
|
|||||||
var recentFeed = ReadAllText(@"Files/Indexers/Avistaz/recentfeed.json");
|
var recentFeed = ReadAllText(@"Files/Indexers/Avistaz/recentfeed.json");
|
||||||
|
|
||||||
Mocker.GetMock<IIndexerHttpClient>()
|
Mocker.GetMock<IIndexerHttpClient>()
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader { { "Content-Type", "application/json" } }, new CookieCollection(), recentFeed)));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader { { "Content-Type", "application/json" } }, new CookieCollection(), recentFeed)));
|
||||||
|
|
||||||
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
@@ -34,7 +35,7 @@ namespace NzbDrone.Core.Test.IndexerTests.AvistazTests
|
|||||||
var recentFeed = ReadAllText(@"Files/Indexers/PrivateHD/recentfeed.json");
|
var recentFeed = ReadAllText(@"Files/Indexers/PrivateHD/recentfeed.json");
|
||||||
|
|
||||||
Mocker.GetMock<IIndexerHttpClient>()
|
Mocker.GetMock<IIndexerHttpClient>()
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader { { "Content-Type", "application/json" } }, new CookieCollection(), recentFeed)));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader { { "Content-Type", "application/json" } }, new CookieCollection(), recentFeed)));
|
||||||
|
|
||||||
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
@@ -33,7 +34,7 @@ namespace NzbDrone.Core.Test.IndexerTests.FileListTests
|
|||||||
var recentFeed = ReadAllText(@"Files/Indexers/FileList/recentfeed.json");
|
var recentFeed = ReadAllText(@"Files/Indexers/FileList/recentfeed.json");
|
||||||
|
|
||||||
Mocker.GetMock<IIndexerHttpClient>()
|
Mocker.GetMock<IIndexerHttpClient>()
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), recentFeed)));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), recentFeed)));
|
||||||
|
|
||||||
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
@@ -45,7 +46,7 @@ namespace NzbDrone.Core.Test.IndexerTests.HDBitsTests
|
|||||||
var responseJson = ReadAllText(fileName);
|
var responseJson = ReadAllText(fileName);
|
||||||
|
|
||||||
Mocker.GetMock<IIndexerHttpClient>()
|
Mocker.GetMock<IIndexerHttpClient>()
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.POST), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Post), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), responseJson)));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), responseJson)));
|
||||||
|
|
||||||
var torrents = (await Subject.Fetch(_movieSearchCriteria)).Releases;
|
var torrents = (await Subject.Fetch(_movieSearchCriteria)).Releases;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
@@ -43,7 +44,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
|||||||
var recentFeed = ReadAllText(@"Files/Indexers/Newznab/newznab_nzb_su.xml");
|
var recentFeed = ReadAllText(@"Files/Indexers/Newznab/newznab_nzb_su.xml");
|
||||||
|
|
||||||
Mocker.GetMock<IIndexerHttpClient>()
|
Mocker.GetMock<IIndexerHttpClient>()
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), recentFeed)));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), recentFeed)));
|
||||||
|
|
||||||
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 }, Limit = 100, Offset = 0 })).Releases;
|
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 }, Limit = 100, Offset = 0 })).Releases;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
@@ -37,11 +38,11 @@ namespace NzbDrone.Core.Test.IndexerTests.PTPTests
|
|||||||
var responseJson = ReadAllText(fileName);
|
var responseJson = ReadAllText(fileName);
|
||||||
|
|
||||||
Mocker.GetMock<IIndexerHttpClient>()
|
Mocker.GetMock<IIndexerHttpClient>()
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.POST), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Post), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), authStream.ToString())));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), authStream.ToString())));
|
||||||
|
|
||||||
Mocker.GetMock<IIndexerHttpClient>()
|
Mocker.GetMock<IIndexerHttpClient>()
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader { ContentType = HttpAccept.Json.Value }, new CookieCollection(), responseJson)));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader { ContentType = HttpAccept.Json.Value }, new CookieCollection(), responseJson)));
|
||||||
|
|
||||||
var torrents = (await Subject.Fetch(new MovieSearchCriteria())).Releases;
|
var torrents = (await Subject.Fetch(new MovieSearchCriteria())).Releases;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
@@ -39,7 +40,7 @@ namespace NzbDrone.Core.Test.IndexerTests.RarbgTests
|
|||||||
var recentFeed = ReadAllText(@"Files/Indexers/Rarbg/RecentFeed_v2.json");
|
var recentFeed = ReadAllText(@"Files/Indexers/Rarbg/RecentFeed_v2.json");
|
||||||
|
|
||||||
Mocker.GetMock<IIndexerHttpClient>()
|
Mocker.GetMock<IIndexerHttpClient>()
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), recentFeed)));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), recentFeed)));
|
||||||
|
|
||||||
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
||||||
@@ -66,7 +67,7 @@ namespace NzbDrone.Core.Test.IndexerTests.RarbgTests
|
|||||||
public async Task should_parse_error_20_as_empty_results()
|
public async Task should_parse_error_20_as_empty_results()
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IIndexerHttpClient>()
|
Mocker.GetMock<IIndexerHttpClient>()
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), "{ error_code: 20, error: \"some message\" }")));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), "{ error_code: 20, error: \"some message\" }")));
|
||||||
|
|
||||||
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
||||||
@@ -78,7 +79,7 @@ namespace NzbDrone.Core.Test.IndexerTests.RarbgTests
|
|||||||
public async Task should_warn_on_unknown_error()
|
public async Task should_warn_on_unknown_error()
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IIndexerHttpClient>()
|
Mocker.GetMock<IIndexerHttpClient>()
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), "{ error_code: 25, error: \"some message\" }")));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), "{ error_code: 25, error: \"some message\" }")));
|
||||||
|
|
||||||
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
@@ -44,7 +45,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorznabTests
|
|||||||
var recentFeed = ReadAllText(@"Files/Indexers/Torznab/torznab_hdaccess_net.xml");
|
var recentFeed = ReadAllText(@"Files/Indexers/Torznab/torznab_hdaccess_net.xml");
|
||||||
|
|
||||||
Mocker.GetMock<IIndexerHttpClient>()
|
Mocker.GetMock<IIndexerHttpClient>()
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), recentFeed)));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), recentFeed)));
|
||||||
|
|
||||||
var releases = (await Subject.Fetch(new MovieSearchCriteria())).Releases;
|
var releases = (await Subject.Fetch(new MovieSearchCriteria())).Releases;
|
||||||
@@ -73,7 +74,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorznabTests
|
|||||||
var recentFeed = ReadAllText(@"Files/Indexers/Torznab/torznab_tpb.xml");
|
var recentFeed = ReadAllText(@"Files/Indexers/Torznab/torznab_tpb.xml");
|
||||||
|
|
||||||
Mocker.GetMock<IIndexerHttpClient>()
|
Mocker.GetMock<IIndexerHttpClient>()
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), recentFeed)));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), recentFeed)));
|
||||||
|
|
||||||
var releases = (await Subject.Fetch(new MovieSearchCriteria())).Releases;
|
var releases = (await Subject.Fetch(new MovieSearchCriteria())).Releases;
|
||||||
@@ -103,7 +104,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorznabTests
|
|||||||
var recentFeed = ReadAllText(@"Files/Indexers/Torznab/torznab_animetosho.xml");
|
var recentFeed = ReadAllText(@"Files/Indexers/Torznab/torznab_animetosho.xml");
|
||||||
|
|
||||||
Mocker.GetMock<IIndexerHttpClient>()
|
Mocker.GetMock<IIndexerHttpClient>()
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), recentFeed)));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader(), new CookieCollection(), recentFeed)));
|
||||||
|
|
||||||
var releases = (await Subject.Fetch(new MovieSearchCriteria())).Releases;
|
var releases = (await Subject.Fetch(new MovieSearchCriteria())).Releases;
|
||||||
|
|||||||
@@ -30,9 +30,27 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||||||
[TestCase("1", 1)]
|
[TestCase("1", 1)]
|
||||||
[TestCase("11", 11)]
|
[TestCase("11", 11)]
|
||||||
[TestCase("1000 grabs", 1000)]
|
[TestCase("1000 grabs", 1000)]
|
||||||
|
[TestCase("2.222", 2222)]
|
||||||
|
[TestCase("2,222", 2222)]
|
||||||
|
[TestCase("2 222", 2222)]
|
||||||
|
[TestCase("2,22", 222)]
|
||||||
public void should_parse_int_from_string(string original, int parsedInt)
|
public void should_parse_int_from_string(string original, int parsedInt)
|
||||||
{
|
{
|
||||||
ParseUtil.CoerceInt(original).Should().Be(parsedInt);
|
ParseUtil.CoerceInt(original).Should().Be(parsedInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase("1.0", 1.0)]
|
||||||
|
[TestCase("1.1", 1.1)]
|
||||||
|
[TestCase("1000 grabs", 1000.0)]
|
||||||
|
[TestCase("2.222", 2.222)]
|
||||||
|
[TestCase("2,222", 2.222)]
|
||||||
|
[TestCase("2.222,22", 2222.22)]
|
||||||
|
[TestCase("2,222.22", 2222.22)]
|
||||||
|
[TestCase("2 222", 2222.0)]
|
||||||
|
[TestCase("2,22", 2.22)]
|
||||||
|
public void should_parse_double_from_string(string original, double parsedInt)
|
||||||
|
{
|
||||||
|
ParseUtil.CoerceDouble(original).Should().Be(parsedInt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -31,13 +32,13 @@ namespace NzbDrone.Core.Applications.LazyLibrarian
|
|||||||
|
|
||||||
public LazyLibrarianStatus GetStatus(LazyLibrarianSettings settings)
|
public LazyLibrarianStatus GetStatus(LazyLibrarianSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api", "getVersion", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api", "getVersion", HttpMethod.Get);
|
||||||
return Execute<LazyLibrarianStatus>(request);
|
return Execute<LazyLibrarianStatus>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<LazyLibrarianIndexer> GetIndexers(LazyLibrarianSettings settings)
|
public List<LazyLibrarianIndexer> GetIndexers(LazyLibrarianSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api", "listNabProviders", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api", "listNabProviders", HttpMethod.Get);
|
||||||
|
|
||||||
var response = Execute<LazyLibrarianIndexerResponse>(request);
|
var response = Execute<LazyLibrarianIndexerResponse>(request);
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@ namespace NzbDrone.Core.Applications.LazyLibrarian
|
|||||||
{ "providertype", indexerType.ToString().ToLower() }
|
{ "providertype", indexerType.ToString().ToLower() }
|
||||||
};
|
};
|
||||||
|
|
||||||
var request = BuildRequest(settings, "/api", "delProvider", HttpMethod.GET, parameters);
|
var request = BuildRequest(settings, "/api", "delProvider", HttpMethod.Get, parameters);
|
||||||
CheckForError(Execute<LazyLibrarianStatus>(request));
|
CheckForError(Execute<LazyLibrarianStatus>(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +93,7 @@ namespace NzbDrone.Core.Applications.LazyLibrarian
|
|||||||
{ "categories", indexer.Categories }
|
{ "categories", indexer.Categories }
|
||||||
};
|
};
|
||||||
|
|
||||||
var request = BuildRequest(settings, "/api", "addProvider", HttpMethod.GET, parameters);
|
var request = BuildRequest(settings, "/api", "addProvider", HttpMethod.Get, parameters);
|
||||||
CheckForError(Execute<LazyLibrarianStatus>(request));
|
CheckForError(Execute<LazyLibrarianStatus>(request));
|
||||||
return indexer;
|
return indexer;
|
||||||
}
|
}
|
||||||
@@ -110,7 +111,7 @@ namespace NzbDrone.Core.Applications.LazyLibrarian
|
|||||||
{ "altername", indexer.Altername }
|
{ "altername", indexer.Altername }
|
||||||
};
|
};
|
||||||
|
|
||||||
var request = BuildRequest(settings, "/api", "changeProvider", HttpMethod.GET, parameters);
|
var request = BuildRequest(settings, "/api", "changeProvider", HttpMethod.Get, parameters);
|
||||||
CheckForError(Execute<LazyLibrarianStatus>(request));
|
CheckForError(Execute<LazyLibrarianStatus>(request));
|
||||||
return indexer;
|
return indexer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -33,13 +34,13 @@ namespace NzbDrone.Core.Applications.Lidarr
|
|||||||
|
|
||||||
public LidarrStatus GetStatus(LidarrSettings settings)
|
public LidarrStatus GetStatus(LidarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v1/system/status", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api/v1/system/status", HttpMethod.Get);
|
||||||
return Execute<LidarrStatus>(request);
|
return Execute<LidarrStatus>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<LidarrIndexer> GetIndexers(LidarrSettings settings)
|
public List<LidarrIndexer> GetIndexers(LidarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v1/indexer", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api/v1/indexer", HttpMethod.Get);
|
||||||
return Execute<List<LidarrIndexer>>(request);
|
return Execute<List<LidarrIndexer>>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ namespace NzbDrone.Core.Applications.Lidarr
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v1/indexer/{indexerId}", HttpMethod.GET);
|
var request = BuildRequest(settings, $"/api/v1/indexer/{indexerId}", HttpMethod.Get);
|
||||||
return Execute<LidarrIndexer>(request);
|
return Execute<LidarrIndexer>(request);
|
||||||
}
|
}
|
||||||
catch (HttpException ex)
|
catch (HttpException ex)
|
||||||
@@ -63,19 +64,19 @@ namespace NzbDrone.Core.Applications.Lidarr
|
|||||||
|
|
||||||
public void RemoveIndexer(int indexerId, LidarrSettings settings)
|
public void RemoveIndexer(int indexerId, LidarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v1/indexer/{indexerId}", HttpMethod.DELETE);
|
var request = BuildRequest(settings, $"/api/v1/indexer/{indexerId}", HttpMethod.Delete);
|
||||||
_httpClient.Execute(request);
|
_httpClient.Execute(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<LidarrIndexer> GetIndexerSchema(LidarrSettings settings)
|
public List<LidarrIndexer> GetIndexerSchema(LidarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v1/indexer/schema", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api/v1/indexer/schema", HttpMethod.Get);
|
||||||
return Execute<List<LidarrIndexer>>(request);
|
return Execute<List<LidarrIndexer>>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LidarrIndexer AddIndexer(LidarrIndexer indexer, LidarrSettings settings)
|
public LidarrIndexer AddIndexer(LidarrIndexer indexer, LidarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v1/indexer", HttpMethod.POST);
|
var request = BuildRequest(settings, "/api/v1/indexer", HttpMethod.Post);
|
||||||
|
|
||||||
request.SetContent(indexer.ToJson());
|
request.SetContent(indexer.ToJson());
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ namespace NzbDrone.Core.Applications.Lidarr
|
|||||||
|
|
||||||
public LidarrIndexer UpdateIndexer(LidarrIndexer indexer, LidarrSettings settings)
|
public LidarrIndexer UpdateIndexer(LidarrIndexer indexer, LidarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v1/indexer/{indexer.Id}", HttpMethod.PUT);
|
var request = BuildRequest(settings, $"/api/v1/indexer/{indexer.Id}", HttpMethod.Put);
|
||||||
|
|
||||||
request.SetContent(indexer.ToJson());
|
request.SetContent(indexer.ToJson());
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ namespace NzbDrone.Core.Applications.Lidarr
|
|||||||
|
|
||||||
public ValidationFailure TestConnection(LidarrIndexer indexer, LidarrSettings settings)
|
public ValidationFailure TestConnection(LidarrIndexer indexer, LidarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v1/indexer/test", HttpMethod.POST);
|
var request = BuildRequest(settings, $"/api/v1/indexer/test", HttpMethod.Post);
|
||||||
|
|
||||||
request.SetContent(indexer.ToJson());
|
request.SetContent(indexer.ToJson());
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -31,13 +32,13 @@ namespace NzbDrone.Core.Applications.Mylar
|
|||||||
|
|
||||||
public MylarStatus GetStatus(MylarSettings settings)
|
public MylarStatus GetStatus(MylarSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api", "getVersion", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api", "getVersion", HttpMethod.Get);
|
||||||
return Execute<MylarStatus>(request);
|
return Execute<MylarStatus>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MylarIndexer> GetIndexers(MylarSettings settings)
|
public List<MylarIndexer> GetIndexers(MylarSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api", "listProviders", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api", "listProviders", HttpMethod.Get);
|
||||||
|
|
||||||
var response = Execute<MylarIndexerResponse>(request);
|
var response = Execute<MylarIndexerResponse>(request);
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@ namespace NzbDrone.Core.Applications.Mylar
|
|||||||
{ "providertype", indexerType.ToString().ToLower() }
|
{ "providertype", indexerType.ToString().ToLower() }
|
||||||
};
|
};
|
||||||
|
|
||||||
var request = BuildRequest(settings, "/api", "delProvider", HttpMethod.GET, parameters);
|
var request = BuildRequest(settings, "/api", "delProvider", HttpMethod.Get, parameters);
|
||||||
CheckForError(Execute<MylarStatus>(request));
|
CheckForError(Execute<MylarStatus>(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +93,7 @@ namespace NzbDrone.Core.Applications.Mylar
|
|||||||
{ "categories", indexer.Categories }
|
{ "categories", indexer.Categories }
|
||||||
};
|
};
|
||||||
|
|
||||||
var request = BuildRequest(settings, "/api", "addProvider", HttpMethod.GET, parameters);
|
var request = BuildRequest(settings, "/api", "addProvider", HttpMethod.Get, parameters);
|
||||||
CheckForError(Execute<MylarStatus>(request));
|
CheckForError(Execute<MylarStatus>(request));
|
||||||
return indexer;
|
return indexer;
|
||||||
}
|
}
|
||||||
@@ -110,7 +111,7 @@ namespace NzbDrone.Core.Applications.Mylar
|
|||||||
{ "altername", indexer.Altername }
|
{ "altername", indexer.Altername }
|
||||||
};
|
};
|
||||||
|
|
||||||
var request = BuildRequest(settings, "/api", "changeProvider", HttpMethod.GET, parameters);
|
var request = BuildRequest(settings, "/api", "changeProvider", HttpMethod.Get, parameters);
|
||||||
CheckForError(Execute<MylarStatus>(request));
|
CheckForError(Execute<MylarStatus>(request));
|
||||||
return indexer;
|
return indexer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -33,13 +34,13 @@ namespace NzbDrone.Core.Applications.Radarr
|
|||||||
|
|
||||||
public RadarrStatus GetStatus(RadarrSettings settings)
|
public RadarrStatus GetStatus(RadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v3/system/status", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api/v3/system/status", HttpMethod.Get);
|
||||||
return Execute<RadarrStatus>(request);
|
return Execute<RadarrStatus>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RadarrIndexer> GetIndexers(RadarrSettings settings)
|
public List<RadarrIndexer> GetIndexers(RadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v3/indexer", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api/v3/indexer", HttpMethod.Get);
|
||||||
return Execute<List<RadarrIndexer>>(request);
|
return Execute<List<RadarrIndexer>>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ namespace NzbDrone.Core.Applications.Radarr
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v3/indexer/{indexerId}", HttpMethod.GET);
|
var request = BuildRequest(settings, $"/api/v3/indexer/{indexerId}", HttpMethod.Get);
|
||||||
return Execute<RadarrIndexer>(request);
|
return Execute<RadarrIndexer>(request);
|
||||||
}
|
}
|
||||||
catch (HttpException ex)
|
catch (HttpException ex)
|
||||||
@@ -63,19 +64,19 @@ namespace NzbDrone.Core.Applications.Radarr
|
|||||||
|
|
||||||
public void RemoveIndexer(int indexerId, RadarrSettings settings)
|
public void RemoveIndexer(int indexerId, RadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v3/indexer/{indexerId}", HttpMethod.DELETE);
|
var request = BuildRequest(settings, $"/api/v3/indexer/{indexerId}", HttpMethod.Delete);
|
||||||
_httpClient.Execute(request);
|
_httpClient.Execute(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RadarrIndexer> GetIndexerSchema(RadarrSettings settings)
|
public List<RadarrIndexer> GetIndexerSchema(RadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v3/indexer/schema", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api/v3/indexer/schema", HttpMethod.Get);
|
||||||
return Execute<List<RadarrIndexer>>(request);
|
return Execute<List<RadarrIndexer>>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RadarrIndexer AddIndexer(RadarrIndexer indexer, RadarrSettings settings)
|
public RadarrIndexer AddIndexer(RadarrIndexer indexer, RadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v3/indexer", HttpMethod.POST);
|
var request = BuildRequest(settings, "/api/v3/indexer", HttpMethod.Post);
|
||||||
|
|
||||||
request.SetContent(indexer.ToJson());
|
request.SetContent(indexer.ToJson());
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ namespace NzbDrone.Core.Applications.Radarr
|
|||||||
|
|
||||||
public RadarrIndexer UpdateIndexer(RadarrIndexer indexer, RadarrSettings settings)
|
public RadarrIndexer UpdateIndexer(RadarrIndexer indexer, RadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v3/indexer/{indexer.Id}", HttpMethod.PUT);
|
var request = BuildRequest(settings, $"/api/v3/indexer/{indexer.Id}", HttpMethod.Put);
|
||||||
|
|
||||||
request.SetContent(indexer.ToJson());
|
request.SetContent(indexer.ToJson());
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ namespace NzbDrone.Core.Applications.Radarr
|
|||||||
|
|
||||||
public ValidationFailure TestConnection(RadarrIndexer indexer, RadarrSettings settings)
|
public ValidationFailure TestConnection(RadarrIndexer indexer, RadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v3/indexer/test", HttpMethod.POST);
|
var request = BuildRequest(settings, $"/api/v3/indexer/test", HttpMethod.Post);
|
||||||
|
|
||||||
request.SetContent(indexer.ToJson());
|
request.SetContent(indexer.ToJson());
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -33,13 +34,13 @@ namespace NzbDrone.Core.Applications.Readarr
|
|||||||
|
|
||||||
public ReadarrStatus GetStatus(ReadarrSettings settings)
|
public ReadarrStatus GetStatus(ReadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v1/system/status", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api/v1/system/status", HttpMethod.Get);
|
||||||
return Execute<ReadarrStatus>(request);
|
return Execute<ReadarrStatus>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ReadarrIndexer> GetIndexers(ReadarrSettings settings)
|
public List<ReadarrIndexer> GetIndexers(ReadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v1/indexer", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api/v1/indexer", HttpMethod.Get);
|
||||||
return Execute<List<ReadarrIndexer>>(request);
|
return Execute<List<ReadarrIndexer>>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ namespace NzbDrone.Core.Applications.Readarr
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v1/indexer/{indexerId}", HttpMethod.GET);
|
var request = BuildRequest(settings, $"/api/v1/indexer/{indexerId}", HttpMethod.Get);
|
||||||
return Execute<ReadarrIndexer>(request);
|
return Execute<ReadarrIndexer>(request);
|
||||||
}
|
}
|
||||||
catch (HttpException ex)
|
catch (HttpException ex)
|
||||||
@@ -63,19 +64,19 @@ namespace NzbDrone.Core.Applications.Readarr
|
|||||||
|
|
||||||
public void RemoveIndexer(int indexerId, ReadarrSettings settings)
|
public void RemoveIndexer(int indexerId, ReadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v1/indexer/{indexerId}", HttpMethod.DELETE);
|
var request = BuildRequest(settings, $"/api/v1/indexer/{indexerId}", HttpMethod.Delete);
|
||||||
_httpClient.Execute(request);
|
_httpClient.Execute(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ReadarrIndexer> GetIndexerSchema(ReadarrSettings settings)
|
public List<ReadarrIndexer> GetIndexerSchema(ReadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v1/indexer/schema", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api/v1/indexer/schema", HttpMethod.Get);
|
||||||
return Execute<List<ReadarrIndexer>>(request);
|
return Execute<List<ReadarrIndexer>>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadarrIndexer AddIndexer(ReadarrIndexer indexer, ReadarrSettings settings)
|
public ReadarrIndexer AddIndexer(ReadarrIndexer indexer, ReadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v1/indexer", HttpMethod.POST);
|
var request = BuildRequest(settings, "/api/v1/indexer", HttpMethod.Post);
|
||||||
|
|
||||||
request.SetContent(indexer.ToJson());
|
request.SetContent(indexer.ToJson());
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ namespace NzbDrone.Core.Applications.Readarr
|
|||||||
|
|
||||||
public ReadarrIndexer UpdateIndexer(ReadarrIndexer indexer, ReadarrSettings settings)
|
public ReadarrIndexer UpdateIndexer(ReadarrIndexer indexer, ReadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v1/indexer/{indexer.Id}", HttpMethod.PUT);
|
var request = BuildRequest(settings, $"/api/v1/indexer/{indexer.Id}", HttpMethod.Put);
|
||||||
|
|
||||||
request.SetContent(indexer.ToJson());
|
request.SetContent(indexer.ToJson());
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ namespace NzbDrone.Core.Applications.Readarr
|
|||||||
|
|
||||||
public ValidationFailure TestConnection(ReadarrIndexer indexer, ReadarrSettings settings)
|
public ValidationFailure TestConnection(ReadarrIndexer indexer, ReadarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v1/indexer/test", HttpMethod.POST);
|
var request = BuildRequest(settings, $"/api/v1/indexer/test", HttpMethod.Post);
|
||||||
|
|
||||||
request.SetContent(indexer.ToJson());
|
request.SetContent(indexer.ToJson());
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -33,13 +34,13 @@ namespace NzbDrone.Core.Applications.Sonarr
|
|||||||
|
|
||||||
public SonarrStatus GetStatus(SonarrSettings settings)
|
public SonarrStatus GetStatus(SonarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v3/system/status", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api/v3/system/status", HttpMethod.Get);
|
||||||
return Execute<SonarrStatus>(request);
|
return Execute<SonarrStatus>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SonarrIndexer> GetIndexers(SonarrSettings settings)
|
public List<SonarrIndexer> GetIndexers(SonarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v3/indexer", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api/v3/indexer", HttpMethod.Get);
|
||||||
return Execute<List<SonarrIndexer>>(request);
|
return Execute<List<SonarrIndexer>>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ namespace NzbDrone.Core.Applications.Sonarr
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v3/indexer/{indexerId}", HttpMethod.GET);
|
var request = BuildRequest(settings, $"/api/v3/indexer/{indexerId}", HttpMethod.Get);
|
||||||
return Execute<SonarrIndexer>(request);
|
return Execute<SonarrIndexer>(request);
|
||||||
}
|
}
|
||||||
catch (HttpException ex)
|
catch (HttpException ex)
|
||||||
@@ -63,19 +64,19 @@ namespace NzbDrone.Core.Applications.Sonarr
|
|||||||
|
|
||||||
public void RemoveIndexer(int indexerId, SonarrSettings settings)
|
public void RemoveIndexer(int indexerId, SonarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v3/indexer/{indexerId}", HttpMethod.DELETE);
|
var request = BuildRequest(settings, $"/api/v3/indexer/{indexerId}", HttpMethod.Delete);
|
||||||
_httpClient.Execute(request);
|
_httpClient.Execute(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SonarrIndexer> GetIndexerSchema(SonarrSettings settings)
|
public List<SonarrIndexer> GetIndexerSchema(SonarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v3/indexer/schema", HttpMethod.GET);
|
var request = BuildRequest(settings, "/api/v3/indexer/schema", HttpMethod.Get);
|
||||||
return Execute<List<SonarrIndexer>>(request);
|
return Execute<List<SonarrIndexer>>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SonarrIndexer AddIndexer(SonarrIndexer indexer, SonarrSettings settings)
|
public SonarrIndexer AddIndexer(SonarrIndexer indexer, SonarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "/api/v3/indexer", HttpMethod.POST);
|
var request = BuildRequest(settings, "/api/v3/indexer", HttpMethod.Post);
|
||||||
|
|
||||||
request.SetContent(indexer.ToJson());
|
request.SetContent(indexer.ToJson());
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ namespace NzbDrone.Core.Applications.Sonarr
|
|||||||
|
|
||||||
public SonarrIndexer UpdateIndexer(SonarrIndexer indexer, SonarrSettings settings)
|
public SonarrIndexer UpdateIndexer(SonarrIndexer indexer, SonarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v3/indexer/{indexer.Id}", HttpMethod.PUT);
|
var request = BuildRequest(settings, $"/api/v3/indexer/{indexer.Id}", HttpMethod.Put);
|
||||||
|
|
||||||
request.SetContent(indexer.ToJson());
|
request.SetContent(indexer.ToJson());
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ namespace NzbDrone.Core.Applications.Sonarr
|
|||||||
|
|
||||||
public ValidationFailure TestConnection(SonarrIndexer indexer, SonarrSettings settings)
|
public ValidationFailure TestConnection(SonarrIndexer indexer, SonarrSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, $"/api/v3/indexer/test", HttpMethod.POST);
|
var request = BuildRequest(settings, $"/api/v3/indexer/test", HttpMethod.Post);
|
||||||
|
|
||||||
request.SetContent(indexer.ToJson());
|
request.SetContent(indexer.ToJson());
|
||||||
|
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ namespace NzbDrone.Core.Configuration
|
|||||||
public string PostgresPassword => GetValue("PostgresPassword", string.Empty, persist: false);
|
public string PostgresPassword => GetValue("PostgresPassword", string.Empty, persist: false);
|
||||||
public string PostgresMainDb => GetValue("PostgresMainDb", "prowlarr-main", persist: false);
|
public string PostgresMainDb => GetValue("PostgresMainDb", "prowlarr-main", persist: false);
|
||||||
public string PostgresLogDb => GetValue("PostgresLogDb", "prowlarr-log", persist: false);
|
public string PostgresLogDb => GetValue("PostgresLogDb", "prowlarr-log", persist: false);
|
||||||
public int PostgresPort => GetValueInt("PostgresPort", 5436, persist: false);
|
public int PostgresPort => GetValueInt("PostgresPort", 5432, persist: false);
|
||||||
public bool LogSql => GetValueBoolean("LogSql", false, persist: false);
|
public bool LogSql => GetValueBoolean("LogSql", false, persist: false);
|
||||||
public int LogRotate => GetValueInt("LogRotate", 50, persist: false);
|
public int LogRotate => GetValueInt("LogRotate", 50, persist: false);
|
||||||
public bool FilterSentryEvents => GetValueBoolean("FilterSentryEvents", true, persist: false);
|
public bool FilterSentryEvents => GetValueBoolean("FilterSentryEvents", true, persist: false);
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(15)]
|
||||||
|
public class IndexerVersions : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Create.TableForModel("IndexerDefinitionVersions")
|
||||||
|
.WithColumn("DefinitionId").AsString().NotNullable().Unique()
|
||||||
|
.WithColumn("File").AsString().NotNullable().Unique()
|
||||||
|
.WithColumn("Sha").AsString().Nullable()
|
||||||
|
.WithColumn("LastUpdated").AsDateTime().Nullable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ using NzbDrone.Core.Datastore.Converters;
|
|||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.IndexerProxies;
|
using NzbDrone.Core.IndexerProxies;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.IndexerVersions;
|
||||||
using NzbDrone.Core.Instrumentation;
|
using NzbDrone.Core.Instrumentation;
|
||||||
using NzbDrone.Core.Jobs;
|
using NzbDrone.Core.Jobs;
|
||||||
using NzbDrone.Core.Languages;
|
using NzbDrone.Core.Languages;
|
||||||
@@ -94,6 +95,7 @@ namespace NzbDrone.Core.Datastore
|
|||||||
Mapper.Entity<UpdateHistory>("UpdateHistory").RegisterModel();
|
Mapper.Entity<UpdateHistory>("UpdateHistory").RegisterModel();
|
||||||
|
|
||||||
Mapper.Entity<AppSyncProfile>("AppSyncProfiles").RegisterModel();
|
Mapper.Entity<AppSyncProfile>("AppSyncProfiles").RegisterModel();
|
||||||
|
Mapper.Entity<IndexerDefinitionVersion>("IndexerDefinitionVersions").RegisterModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RegisterMappers()
|
private static void RegisterMappers()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Cache;
|
using NzbDrone.Common.Cache;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
@@ -142,15 +143,19 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
|||||||
return authResponse.Data.SId;
|
return authResponse.Data.SId;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HttpRequestBuilder BuildRequest(DownloadStationSettings settings, string methodName, int apiVersion, HttpMethod httpVerb = HttpMethod.GET)
|
protected HttpRequestBuilder BuildRequest(DownloadStationSettings settings, string methodName, int apiVersion, HttpMethod httpVerb = null)
|
||||||
{
|
{
|
||||||
|
httpVerb ??= HttpMethod.Get;
|
||||||
|
|
||||||
var info = GetApiInfo(_apiType, settings);
|
var info = GetApiInfo(_apiType, settings);
|
||||||
|
|
||||||
return BuildRequest(settings, info, methodName, apiVersion, httpVerb);
|
return BuildRequest(settings, info, methodName, apiVersion, httpVerb);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpRequestBuilder BuildRequest(DownloadStationSettings settings, DiskStationApiInfo apiInfo, string methodName, int apiVersion, HttpMethod httpVerb = HttpMethod.GET)
|
private HttpRequestBuilder BuildRequest(DownloadStationSettings settings, DiskStationApiInfo apiInfo, string methodName, int apiVersion, HttpMethod httpVerb = null)
|
||||||
{
|
{
|
||||||
|
httpVerb ??= HttpMethod.Get;
|
||||||
|
|
||||||
var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port).Resource($"webapi/{apiInfo.Path}");
|
var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port).Resource($"webapi/{apiInfo.Path}");
|
||||||
requestBuilder.Method = httpVerb;
|
requestBuilder.Method = httpVerb;
|
||||||
requestBuilder.LogResponseContent = true;
|
requestBuilder.LogResponseContent = true;
|
||||||
@@ -163,7 +168,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
|||||||
throw new ArgumentOutOfRangeException(nameof(apiVersion));
|
throw new ArgumentOutOfRangeException(nameof(apiVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (httpVerb == HttpMethod.POST)
|
if (httpVerb == HttpMethod.Post)
|
||||||
{
|
{
|
||||||
if (apiInfo.NeedsAuthentication)
|
if (apiInfo.NeedsAuthentication)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Cache;
|
using NzbDrone.Common.Cache;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
@@ -24,7 +25,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
|||||||
|
|
||||||
public void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings)
|
public void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings)
|
||||||
{
|
{
|
||||||
var requestBuilder = BuildRequest(settings, "create", 2, HttpMethod.POST);
|
var requestBuilder = BuildRequest(settings, "create", 2, HttpMethod.Post);
|
||||||
|
|
||||||
if (downloadDirectory.IsNotNullOrWhiteSpace())
|
if (downloadDirectory.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Cache;
|
using NzbDrone.Common.Cache;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
@@ -107,7 +108,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
|||||||
{
|
{
|
||||||
var verifyRequest = BuildRequest(settings).Resource("/auth/verify").Build();
|
var verifyRequest = BuildRequest(settings).Resource("/auth/verify").Build();
|
||||||
|
|
||||||
verifyRequest.Method = HttpMethod.GET;
|
verifyRequest.Method = HttpMethod.Get;
|
||||||
|
|
||||||
HandleRequest(verifyRequest, settings);
|
HandleRequest(verifyRequest, settings);
|
||||||
}
|
}
|
||||||
@@ -180,7 +181,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
|||||||
{
|
{
|
||||||
var getTorrentsRequest = BuildRequest(settings).Resource("/torrents").Build();
|
var getTorrentsRequest = BuildRequest(settings).Resource("/torrents").Build();
|
||||||
|
|
||||||
getTorrentsRequest.Method = HttpMethod.GET;
|
getTorrentsRequest.Method = HttpMethod.Get;
|
||||||
|
|
||||||
return Json.Deserialize<TorrentListSummary>(HandleRequest(getTorrentsRequest, settings).Content).Torrents;
|
return Json.Deserialize<TorrentListSummary>(HandleRequest(getTorrentsRequest, settings).Content).Torrents;
|
||||||
}
|
}
|
||||||
@@ -189,7 +190,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
|||||||
{
|
{
|
||||||
var contentsRequest = BuildRequest(settings).Resource($"/torrents/{hash}/contents").Build();
|
var contentsRequest = BuildRequest(settings).Resource($"/torrents/{hash}/contents").Build();
|
||||||
|
|
||||||
contentsRequest.Method = HttpMethod.GET;
|
contentsRequest.Method = HttpMethod.Get;
|
||||||
|
|
||||||
return Json.Deserialize<List<TorrentContent>>(HandleRequest(contentsRequest, settings).Content).ConvertAll(content => content.Path);
|
return Json.Deserialize<List<TorrentContent>>(HandleRequest(contentsRequest, settings).Content).ConvertAll(content => content.Path);
|
||||||
}
|
}
|
||||||
@@ -198,7 +199,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
|||||||
{
|
{
|
||||||
var tagsRequest = BuildRequest(settings).Resource("/torrents/tags").Build();
|
var tagsRequest = BuildRequest(settings).Resource("/torrents/tags").Build();
|
||||||
|
|
||||||
tagsRequest.Method = HttpMethod.PATCH;
|
tagsRequest.Method = HttpMethod.Patch;
|
||||||
|
|
||||||
var body = new Dictionary<string, object>
|
var body = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
|||||||
[FieldDefinition(8, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(RTorrentPriority), HelpText = "Priority to use when grabbing items")]
|
[FieldDefinition(8, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(RTorrentPriority), HelpText = "Priority to use when grabbing items")]
|
||||||
public int Priority { get; set; }
|
public int Priority { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(9, Label = "Add Stopped", Type = FieldType.Checkbox, HelpText = "Enabling will prevent magnets from downloading before downloading")]
|
[FieldDefinition(9, Label = "Add Stopped", Type = FieldType.Checkbox, HelpText = "Enabling will add torrents and magnets to ruTorrent in a stopped state")]
|
||||||
public bool AddStopped { get; set; }
|
public bool AddStopped { get; set; }
|
||||||
|
|
||||||
public NzbDroneValidationResult Validate()
|
public NzbDroneValidationResult Validate()
|
||||||
|
|||||||
48
src/NzbDrone.Core/HealthCheck/Checks/NoDefinitionCheck.cs
Normal file
48
src/NzbDrone.Core/HealthCheck/Checks/NoDefinitionCheck.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Indexers.Cardigann;
|
||||||
|
using NzbDrone.Core.IndexerVersions;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
|
using NzbDrone.Core.ThingiProvider.Events;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.HealthCheck.Checks
|
||||||
|
{
|
||||||
|
[CheckOn(typeof(ProviderDeletedEvent<IIndexer>))]
|
||||||
|
public class NoDefinitionCheck : HealthCheckBase
|
||||||
|
{
|
||||||
|
private readonly IIndexerDefinitionUpdateService _indexerDefinitionUpdateService;
|
||||||
|
private readonly IIndexerFactory _indexerFactory;
|
||||||
|
|
||||||
|
public NoDefinitionCheck(IIndexerDefinitionUpdateService indexerDefinitionUpdateService, IIndexerFactory indexerFactory, ILocalizationService localizationService)
|
||||||
|
: base(localizationService)
|
||||||
|
{
|
||||||
|
_indexerDefinitionUpdateService = indexerDefinitionUpdateService;
|
||||||
|
_indexerFactory = indexerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override HealthCheck Check()
|
||||||
|
{
|
||||||
|
var currentDefs = _indexerDefinitionUpdateService.All();
|
||||||
|
|
||||||
|
var noDefIndexers = _indexerFactory.AllProviders(false)
|
||||||
|
.Where(i => i.Definition.Implementation == "Cardigann" && !currentDefs.Any(d => d.File == ((CardigannSettings)i.Definition.Settings).DefinitionFile)).ToList();
|
||||||
|
|
||||||
|
if (noDefIndexers.Count == 0)
|
||||||
|
{
|
||||||
|
return new HealthCheck(GetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
var healthType = HealthCheckResult.Error;
|
||||||
|
var healthMessage = string.Format(_localizationService.GetLocalizedString("IndexerNoDefCheckMessage"),
|
||||||
|
string.Join(", ", noDefIndexers.Select(v => v.Definition.Name)));
|
||||||
|
|
||||||
|
return new HealthCheck(GetType(),
|
||||||
|
healthType,
|
||||||
|
healthMessage,
|
||||||
|
"#indexers-have-no-definition");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CheckOnSchedule => false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,10 +35,13 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||||||
return new HealthCheck(GetType());
|
return new HealthCheck(GetType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var healthType = HealthCheckResult.Warning;
|
||||||
|
var healthMessage = string.Format(_localizationService.GetLocalizedString("IndexerObsoleteCheckMessage"),
|
||||||
|
string.Join(", ", oldIndexers.Select(v => v.Definition.Name)));
|
||||||
|
|
||||||
return new HealthCheck(GetType(),
|
return new HealthCheck(GetType(),
|
||||||
HealthCheckResult.Warning,
|
healthType,
|
||||||
string.Format(_localizationService.GetLocalizedString("IndexerObsoleteCheckMessage"),
|
healthMessage,
|
||||||
string.Join(", ", oldIndexers.Select(v => v.Definition.Name))),
|
|
||||||
"#indexers-are-obsolete");
|
"#indexers-are-obsolete");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -115,7 +116,7 @@ namespace NzbDrone.Core.IndexerProxies.FlareSolverr
|
|||||||
var userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36";
|
var userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36";
|
||||||
var maxTimeout = Settings.RequestTimeout * 1000;
|
var maxTimeout = Settings.RequestTimeout * 1000;
|
||||||
|
|
||||||
if (request.Method == HttpMethod.GET)
|
if (request.Method == HttpMethod.Get)
|
||||||
{
|
{
|
||||||
req = new FlareSolverrRequestGet
|
req = new FlareSolverrRequestGet
|
||||||
{
|
{
|
||||||
@@ -125,7 +126,7 @@ namespace NzbDrone.Core.IndexerProxies.FlareSolverr
|
|||||||
UserAgent = userAgent
|
UserAgent = userAgent
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (request.Method == HttpMethod.POST)
|
else if (request.Method == HttpMethod.Post)
|
||||||
{
|
{
|
||||||
var contentTypeType = request.Headers.ContentType;
|
var contentTypeType = request.Headers.ContentType;
|
||||||
|
|
||||||
@@ -167,7 +168,7 @@ namespace NzbDrone.Core.IndexerProxies.FlareSolverr
|
|||||||
var newRequest = new HttpRequest(apiUrl, HttpAccept.Json);
|
var newRequest = new HttpRequest(apiUrl, HttpAccept.Json);
|
||||||
|
|
||||||
newRequest.Headers.ContentType = "application/json";
|
newRequest.Headers.ContentType = "application/json";
|
||||||
newRequest.Method = HttpMethod.POST;
|
newRequest.Method = HttpMethod.Post;
|
||||||
newRequest.SetContent(req.ToJson());
|
newRequest.SetContent(req.ToJson());
|
||||||
|
|
||||||
_logger.Debug("Applying FlareSolverr Proxy {0} to request {1}", Name, request.Url);
|
_logger.Debug("Applying FlareSolverr Proxy {0} to request {1}", Name, request.Url);
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ namespace NzbDrone.Core.IndexerSearch
|
|||||||
|
|
||||||
private async Task<List<ReleaseInfo>> Dispatch(Func<IIndexer, Task<IndexerPageableQueryResult>> searchAction, SearchCriteriaBase criteriaBase)
|
private async Task<List<ReleaseInfo>> Dispatch(Func<IIndexer, Task<IndexerPageableQueryResult>> searchAction, SearchCriteriaBase criteriaBase)
|
||||||
{
|
{
|
||||||
var indexers = _indexerFactory.GetAvailableProviders();
|
var indexers = _indexerFactory.Enabled();
|
||||||
|
|
||||||
if (criteriaBase.IndexerIds != null && criteriaBase.IndexerIds.Count > 0)
|
if (criteriaBase.IndexerIds != null && criteriaBase.IndexerIds.Count > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ using NLog;
|
|||||||
using NzbDrone.Common.Cache;
|
using NzbDrone.Common.Cache;
|
||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Extensions;
|
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Indexers.Cardigann;
|
using NzbDrone.Core.Indexers.Cardigann;
|
||||||
|
using NzbDrone.Core.Lifecycle;
|
||||||
using NzbDrone.Core.Messaging.Commands;
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using YamlDotNet.Serialization;
|
using YamlDotNet.Serialization;
|
||||||
using YamlDotNet.Serialization.NamingConventions;
|
using YamlDotNet.Serialization.NamingConventions;
|
||||||
|
|
||||||
@@ -18,15 +19,18 @@ namespace NzbDrone.Core.IndexerVersions
|
|||||||
public interface IIndexerDefinitionUpdateService
|
public interface IIndexerDefinitionUpdateService
|
||||||
{
|
{
|
||||||
List<CardigannMetaDefinition> All();
|
List<CardigannMetaDefinition> All();
|
||||||
CardigannDefinition GetDefinition(string fileKey);
|
CardigannDefinition GetCachedDefinition(string fileKey);
|
||||||
List<string> GetBlocklist();
|
List<string> GetBlocklist();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class IndexerDefinitionUpdateService : IIndexerDefinitionUpdateService, IExecute<IndexerDefinitionUpdateCommand>
|
public class IndexerDefinitionUpdateService : IIndexerDefinitionUpdateService, IExecute<IndexerDefinitionUpdateCommand>, IHandle<ApplicationStartedEvent>
|
||||||
{
|
{
|
||||||
/* Update Service will fall back if version # does not exist for an indexer per Ta */
|
/* Update Service will fall back if version # does not exist for an indexer per Ta */
|
||||||
|
|
||||||
|
private const string DEFINITION_BRANCH = "master";
|
||||||
private const int DEFINITION_VERSION = 3;
|
private const int DEFINITION_VERSION = 3;
|
||||||
|
|
||||||
|
//Used when moving yml to C#
|
||||||
private readonly List<string> _defintionBlocklist = new List<string>()
|
private readonly List<string> _defintionBlocklist = new List<string>()
|
||||||
{
|
{
|
||||||
"aither",
|
"aither",
|
||||||
@@ -49,6 +53,7 @@ namespace NzbDrone.Core.IndexerVersions
|
|||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly IAppFolderInfo _appFolderInfo;
|
private readonly IAppFolderInfo _appFolderInfo;
|
||||||
private readonly IDiskProvider _diskProvider;
|
private readonly IDiskProvider _diskProvider;
|
||||||
|
private readonly IIndexerDefinitionVersionService _versionService;
|
||||||
private readonly ICached<CardigannDefinition> _cache;
|
private readonly ICached<CardigannDefinition> _cache;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
@@ -60,11 +65,13 @@ namespace NzbDrone.Core.IndexerVersions
|
|||||||
public IndexerDefinitionUpdateService(IHttpClient httpClient,
|
public IndexerDefinitionUpdateService(IHttpClient httpClient,
|
||||||
IAppFolderInfo appFolderInfo,
|
IAppFolderInfo appFolderInfo,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
IIndexerDefinitionVersionService versionService,
|
||||||
ICacheManager cacheManager,
|
ICacheManager cacheManager,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_appFolderInfo = appFolderInfo;
|
_appFolderInfo = appFolderInfo;
|
||||||
_diskProvider = diskProvider;
|
_diskProvider = diskProvider;
|
||||||
|
_versionService = versionService;
|
||||||
_cache = cacheManager.GetCache<CardigannDefinition>(typeof(CardigannDefinition), "definitions");
|
_cache = cacheManager.GetCache<CardigannDefinition>(typeof(CardigannDefinition), "definitions");
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@@ -76,43 +83,24 @@ namespace NzbDrone.Core.IndexerVersions
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var request = new HttpRequest($"https://indexers.prowlarr.com/master/{DEFINITION_VERSION}");
|
// Grab latest def list from server or fallback to disk
|
||||||
var response = _httpClient.Get<List<CardigannMetaDefinition>>(request);
|
try
|
||||||
indexerList = response.Resource.Where(i => !_defintionBlocklist.Contains(i.File)).ToList();
|
|
||||||
|
|
||||||
var definitionFolder = Path.Combine(_appFolderInfo.AppDataFolder, "Definitions", "Custom");
|
|
||||||
|
|
||||||
var directoryInfo = new DirectoryInfo(definitionFolder);
|
|
||||||
|
|
||||||
if (directoryInfo.Exists)
|
|
||||||
{
|
{
|
||||||
var files = directoryInfo.GetFiles($"*.yml");
|
var request = new HttpRequest($"https://indexers.prowlarr.com/{DEFINITION_BRANCH}/{DEFINITION_VERSION}");
|
||||||
|
var response = _httpClient.Get<List<CardigannMetaDefinition>>(request);
|
||||||
foreach (var file in files)
|
indexerList = response.Resource.Where(i => !_defintionBlocklist.Contains(i.File)).ToList();
|
||||||
{
|
|
||||||
_logger.Debug("Loading Custom Cardigann definition " + file.FullName);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var definitionString = File.ReadAllText(file.FullName);
|
|
||||||
var definition = _deserializer.Deserialize<CardigannMetaDefinition>(definitionString);
|
|
||||||
|
|
||||||
definition.File = Path.GetFileNameWithoutExtension(file.Name);
|
|
||||||
|
|
||||||
if (indexerList.Any(i => i.File == definition.File || i.Name == definition.Name))
|
|
||||||
{
|
|
||||||
_logger.Warn("Custom Cardigann definition {0} does not have unique file name or Indexer name", file.FullName);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
indexerList.Add(definition);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_logger.Error($"Error while parsing custom Cardigann definition {file.FullName}\n{e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
var definitionFolder = Path.Combine(_appFolderInfo.AppDataFolder, "Definitions");
|
||||||
|
|
||||||
|
indexerList = ReadDefinitionsFromDisk(indexerList, definitionFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check for custom definitions
|
||||||
|
var customDefinitionFolder = Path.Combine(_appFolderInfo.AppDataFolder, "Definitions", "Custom");
|
||||||
|
|
||||||
|
indexerList = ReadDefinitionsFromDisk(indexerList, customDefinitionFolder);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -122,14 +110,14 @@ namespace NzbDrone.Core.IndexerVersions
|
|||||||
return indexerList;
|
return indexerList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardigannDefinition GetDefinition(string file)
|
public CardigannDefinition GetCachedDefinition(string fileKey)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(file))
|
if (string.IsNullOrEmpty(fileKey))
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(file));
|
throw new ArgumentNullException(nameof(fileKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
var definition = _cache.Get(file, () => LoadIndexerDef(file));
|
var definition = _cache.Get(fileKey, () => GetUncachedDefinition(fileKey));
|
||||||
|
|
||||||
return definition;
|
return definition;
|
||||||
}
|
}
|
||||||
@@ -139,15 +127,46 @@ namespace NzbDrone.Core.IndexerVersions
|
|||||||
return _defintionBlocklist;
|
return _defintionBlocklist;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CardigannDefinition GetHttpDefinition(string id)
|
private List<CardigannMetaDefinition> ReadDefinitionsFromDisk(List<CardigannMetaDefinition> defs, string path, SearchOption options = SearchOption.TopDirectoryOnly)
|
||||||
{
|
{
|
||||||
var req = new HttpRequest($"https://indexers.prowlarr.com/master/{DEFINITION_VERSION}/{id}");
|
var indexerList = defs;
|
||||||
var response = _httpClient.Get(req);
|
|
||||||
var definition = _deserializer.Deserialize<CardigannDefinition>(response.Content);
|
var directoryInfo = new DirectoryInfo(path);
|
||||||
return CleanIndexerDefinition(definition);
|
|
||||||
|
if (directoryInfo.Exists)
|
||||||
|
{
|
||||||
|
var files = directoryInfo.GetFiles($"*.yml", options);
|
||||||
|
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
_logger.Debug("Loading definition " + file.FullName);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var definitionString = File.ReadAllText(file.FullName);
|
||||||
|
var definition = _deserializer.Deserialize<CardigannMetaDefinition>(definitionString);
|
||||||
|
|
||||||
|
definition.File = Path.GetFileNameWithoutExtension(file.Name);
|
||||||
|
|
||||||
|
if (indexerList.Any(i => i.File == definition.File || i.Name == definition.Name))
|
||||||
|
{
|
||||||
|
_logger.Warn("Definition {0} does not have unique file name or Indexer name", file.FullName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
indexerList.Add(definition);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Error($"Error while parsing Cardigann definition {file.FullName}\n{e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return indexerList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CardigannDefinition LoadIndexerDef(string fileKey)
|
private CardigannDefinition GetUncachedDefinition(string fileKey)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(fileKey))
|
if (string.IsNullOrEmpty(fileKey))
|
||||||
{
|
{
|
||||||
@@ -182,9 +201,26 @@ namespace NzbDrone.Core.IndexerVersions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dbDefs = _versionService.All();
|
||||||
|
|
||||||
|
//Check to ensure it's in versioned defs before we go to web
|
||||||
|
if (dbDefs.Count > 0 && dbDefs.Any(x => x.File == fileKey))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(fileKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
//No definition was returned locally, go to the web
|
||||||
return GetHttpDefinition(fileKey);
|
return GetHttpDefinition(fileKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CardigannDefinition GetHttpDefinition(string id)
|
||||||
|
{
|
||||||
|
var req = new HttpRequest($"https://indexers.prowlarr.com/{DEFINITION_BRANCH}/{DEFINITION_VERSION}/{id}");
|
||||||
|
var response = _httpClient.Get(req);
|
||||||
|
var definition = _deserializer.Deserialize<CardigannDefinition>(response.Content);
|
||||||
|
return CleanIndexerDefinition(definition);
|
||||||
|
}
|
||||||
|
|
||||||
private CardigannDefinition CleanIndexerDefinition(CardigannDefinition definition)
|
private CardigannDefinition CleanIndexerDefinition(CardigannDefinition definition)
|
||||||
{
|
{
|
||||||
if (definition.Settings == null)
|
if (definition.Settings == null)
|
||||||
@@ -224,6 +260,12 @@ namespace NzbDrone.Core.IndexerVersions
|
|||||||
return definition;
|
return definition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Handle(ApplicationStartedEvent message)
|
||||||
|
{
|
||||||
|
// Sync indexers on app start
|
||||||
|
UpdateLocalDefinitions();
|
||||||
|
}
|
||||||
|
|
||||||
public void Execute(IndexerDefinitionUpdateCommand message)
|
public void Execute(IndexerDefinitionUpdateCommand message)
|
||||||
{
|
{
|
||||||
UpdateLocalDefinitions();
|
UpdateLocalDefinitions();
|
||||||
@@ -238,30 +280,47 @@ namespace NzbDrone.Core.IndexerVersions
|
|||||||
|
|
||||||
private void UpdateLocalDefinitions()
|
private void UpdateLocalDefinitions()
|
||||||
{
|
{
|
||||||
var request = new HttpRequest($"https://indexers.prowlarr.com/master/{DEFINITION_VERSION}");
|
var startupFolder = _appFolderInfo.AppDataFolder;
|
||||||
|
|
||||||
|
var request = new HttpRequest($"https://indexers.prowlarr.com/{DEFINITION_BRANCH}/{DEFINITION_VERSION}");
|
||||||
var response = _httpClient.Get<List<CardigannMetaDefinition>>(request);
|
var response = _httpClient.Get<List<CardigannMetaDefinition>>(request);
|
||||||
|
|
||||||
foreach (var def in response.Resource)
|
var currentDefs = _versionService.All().ToDictionary(x => x.DefinitionId, x => x.Sha);
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
EnsureDefinitionsFolder();
|
||||||
|
|
||||||
|
foreach (var def in response.Resource)
|
||||||
{
|
{
|
||||||
var startupFolder = _appFolderInfo.AppDataFolder;
|
try
|
||||||
|
{
|
||||||
|
var saveFile = Path.Combine(startupFolder, "Definitions", $"{def.File}.yml");
|
||||||
|
|
||||||
EnsureDefinitionsFolder();
|
if (currentDefs.TryGetValue(def.Id, out var defSha) && defSha == def.Sha)
|
||||||
|
{
|
||||||
|
_logger.Trace("Indexer already up to date: {0}", def.File);
|
||||||
|
|
||||||
var saveFile = Path.Combine(startupFolder, "Definitions", $"{def.File}.yml");
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
_httpClient.DownloadFile($"https://indexers.prowlarr.com/master/{DEFINITION_VERSION}/{def.File}", saveFile);
|
_httpClient.DownloadFile($"https://indexers.prowlarr.com/{DEFINITION_BRANCH}/{DEFINITION_VERSION}/{def.File}", saveFile);
|
||||||
|
|
||||||
_cache.Remove(def.File);
|
_versionService.Upsert(new IndexerDefinitionVersion { Sha = def.Sha, DefinitionId = def.Id, File = def.File, LastUpdated = DateTime.UtcNow });
|
||||||
|
|
||||||
_logger.Debug("Updated definition: {0}", def.File);
|
_cache.Remove(def.File);
|
||||||
}
|
_logger.Debug("Updated definition: {0}", def.File);
|
||||||
catch (Exception ex)
|
}
|
||||||
{
|
catch (Exception ex)
|
||||||
_logger.Error("Definition download failed: {0}, {1}", def.File, ex.Message);
|
{
|
||||||
|
_logger.Error("Definition download failed: {0}, {1}", def.File, ex.Message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error(ex, "Definition download failed, error creating definitions folder in {0}", startupFolder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.IndexerVersions
|
||||||
|
{
|
||||||
|
public class IndexerDefinitionVersion : ModelBase
|
||||||
|
{
|
||||||
|
public string File { get; set; }
|
||||||
|
public string Sha { get; set; }
|
||||||
|
public DateTime LastUpdated { get; set; }
|
||||||
|
public string DefinitionId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.IndexerVersions
|
||||||
|
{
|
||||||
|
public interface IIndexerDefinitionVersionRepository : IBasicRepository<IndexerDefinitionVersion>
|
||||||
|
{
|
||||||
|
public IndexerDefinitionVersion GetByDefId(string defId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IndexerDefinitionVersionRepository : BasicRepository<IndexerDefinitionVersion>, IIndexerDefinitionVersionRepository
|
||||||
|
{
|
||||||
|
public IndexerDefinitionVersionRepository(IMainDatabase database, IEventAggregator eventAggregator)
|
||||||
|
: base(database, eventAggregator)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexerDefinitionVersion GetByDefId(string defId)
|
||||||
|
{
|
||||||
|
return Query(x => x.DefinitionId == defId).SingleOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.IndexerVersions
|
||||||
|
{
|
||||||
|
public interface IIndexerDefinitionVersionService
|
||||||
|
{
|
||||||
|
IndexerDefinitionVersion Get(int indexerVersionId);
|
||||||
|
IndexerDefinitionVersion GetByDefId(string defId);
|
||||||
|
List<IndexerDefinitionVersion> All();
|
||||||
|
IndexerDefinitionVersion Add(IndexerDefinitionVersion defVersion);
|
||||||
|
IndexerDefinitionVersion Upsert(IndexerDefinitionVersion defVersion);
|
||||||
|
void Delete(int indexerVersionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IndexerDefinitionVersionService : IIndexerDefinitionVersionService
|
||||||
|
{
|
||||||
|
private readonly IIndexerDefinitionVersionRepository _repo;
|
||||||
|
|
||||||
|
public IndexerDefinitionVersionService(IIndexerDefinitionVersionRepository repo)
|
||||||
|
{
|
||||||
|
_repo = repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexerDefinitionVersion Get(int indexerVersionId)
|
||||||
|
{
|
||||||
|
return _repo.Get(indexerVersionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexerDefinitionVersion GetByDefId(string defId)
|
||||||
|
{
|
||||||
|
return _repo.GetByDefId(defId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IndexerDefinitionVersion> All()
|
||||||
|
{
|
||||||
|
return _repo.All().ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexerDefinitionVersion Add(IndexerDefinitionVersion defVersion)
|
||||||
|
{
|
||||||
|
_repo.Insert(defVersion);
|
||||||
|
|
||||||
|
return defVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexerDefinitionVersion Upsert(IndexerDefinitionVersion defVersion)
|
||||||
|
{
|
||||||
|
var existing = _repo.GetByDefId(defVersion.DefinitionId);
|
||||||
|
|
||||||
|
if (existing != null)
|
||||||
|
{
|
||||||
|
defVersion.Id = existing.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
defVersion = _repo.Upsert(defVersion);
|
||||||
|
|
||||||
|
return defVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delete(int indexerVersionId)
|
||||||
|
{
|
||||||
|
_repo.Delete(indexerVersionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,7 +60,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
|
|
||||||
var mainPage = await ExecuteAuth(new HttpRequest(Settings.BaseUrl));
|
var mainPage = await ExecuteAuth(new HttpRequest(Settings.BaseUrl));
|
||||||
|
|
||||||
requestBuilder.Method = Common.Http.HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
requestBuilder.SetCookies(mainPage.GetCookies());
|
requestBuilder.SetCookies(mainPage.GetCookies());
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
|
|
||||||
if (isSearch)
|
if (isSearch)
|
||||||
{
|
{
|
||||||
request.HttpRequest.Method = NzbDrone.Common.Http.HttpMethod.POST;
|
request.HttpRequest.Method = HttpMethod.Post;
|
||||||
var postData = new NameValueCollection
|
var postData = new NameValueCollection
|
||||||
{
|
{
|
||||||
{ "do", "search" },
|
{ "do", "search" },
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AngleSharp.Html.Parser;
|
using AngleSharp.Html.Parser;
|
||||||
@@ -57,7 +58,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
};
|
};
|
||||||
|
|
||||||
var loginPage = await ExecuteAuth(new HttpRequest(LoginUrl));
|
var loginPage = await ExecuteAuth(new HttpRequest(LoginUrl));
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
requestBuilder.SetCookies(loginPage.GetCookies());
|
requestBuilder.SetCookies(loginPage.GetCookies());
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AngleSharp.Html.Parser;
|
using AngleSharp.Html.Parser;
|
||||||
@@ -56,7 +57,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
AllowAutoRedirect = true
|
AllowAutoRedirect = true
|
||||||
};
|
};
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
|
|
||||||
var cookies = Cookies;
|
var cookies = Cookies;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -105,7 +106,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
|
|||||||
LogResponseContent = true
|
LogResponseContent = true
|
||||||
};
|
};
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
|
|
||||||
var authLoginRequest = requestBuilder
|
var authLoginRequest = requestBuilder
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -55,7 +56,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
AllowAutoRedirect = true
|
AllowAutoRedirect = true
|
||||||
};
|
};
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
|
|
||||||
var cookies = Cookies;
|
var cookies = Cookies;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AngleSharp.Dom;
|
using AngleSharp.Dom;
|
||||||
@@ -79,7 +80,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
|
|
||||||
var loginPage = await ExecuteAuth(new HttpRequest(LoginUrl));
|
var loginPage = await ExecuteAuth(new HttpRequest(LoginUrl));
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
requestBuilder.SetCookies(loginPage.GetCookies());
|
requestBuilder.SetCookies(loginPage.GetCookies());
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -110,7 +111,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
var request = new HttpRequest(searchUrl, HttpAccept.Json);
|
var request = new HttpRequest(searchUrl, HttpAccept.Json);
|
||||||
|
|
||||||
request.Headers.Add("Content-type", "application/json");
|
request.Headers.Add("Content-type", "application/json");
|
||||||
request.Method = HttpMethod.POST;
|
request.Method = HttpMethod.Post;
|
||||||
request.SetContent(body.ToJson());
|
request.SetContent(body.ToJson());
|
||||||
|
|
||||||
var indexerRequest = new IndexerRequest(request);
|
var indexerRequest = new IndexerRequest(request);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
{
|
{
|
||||||
var generator = _generatorCache.Get(Settings.DefinitionFile, () =>
|
var generator = _generatorCache.Get(Settings.DefinitionFile, () =>
|
||||||
new CardigannRequestGenerator(_configService,
|
new CardigannRequestGenerator(_configService,
|
||||||
_definitionService.GetDefinition(Settings.DefinitionFile),
|
_definitionService.GetCachedDefinition(Settings.DefinitionFile),
|
||||||
_logger)
|
_logger)
|
||||||
{
|
{
|
||||||
HttpClient = _httpClient,
|
HttpClient = _httpClient,
|
||||||
@@ -57,7 +57,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
public override IParseIndexerResponse GetParser()
|
public override IParseIndexerResponse GetParser()
|
||||||
{
|
{
|
||||||
return new CardigannParser(_configService,
|
return new CardigannParser(_configService,
|
||||||
_definitionService.GetDefinition(Settings.DefinitionFile),
|
_definitionService.GetCachedDefinition(Settings.DefinitionFile),
|
||||||
_logger)
|
_logger)
|
||||||
{
|
{
|
||||||
Settings = Settings
|
Settings = Settings
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AngleSharp.Html.Dom;
|
using AngleSharp.Html.Dom;
|
||||||
@@ -184,7 +185,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
var requestBuilder = new HttpRequestBuilder(loginUrl)
|
var requestBuilder = new HttpRequestBuilder(loginUrl)
|
||||||
{
|
{
|
||||||
LogResponseContent = true,
|
LogResponseContent = true,
|
||||||
Method = HttpMethod.POST,
|
Method = HttpMethod.Post,
|
||||||
AllowAutoRedirect = true,
|
AllowAutoRedirect = true,
|
||||||
SuppressHttpError = true,
|
SuppressHttpError = true,
|
||||||
Encoding = _encoding
|
Encoding = _encoding
|
||||||
@@ -329,7 +330,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
var requestBuilder = new HttpRequestBuilder(captchaUrl.ToString())
|
var requestBuilder = new HttpRequestBuilder(captchaUrl.ToString())
|
||||||
{
|
{
|
||||||
LogResponseContent = true,
|
LogResponseContent = true,
|
||||||
Method = HttpMethod.GET,
|
Method = HttpMethod.Get,
|
||||||
Encoding = _encoding
|
Encoding = _encoding
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -394,7 +395,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
var requestBuilder = new HttpRequestBuilder(submitUrl.ToString())
|
var requestBuilder = new HttpRequestBuilder(submitUrl.ToString())
|
||||||
{
|
{
|
||||||
LogResponseContent = true,
|
LogResponseContent = true,
|
||||||
Method = HttpMethod.POST,
|
Method = HttpMethod.Post,
|
||||||
AllowAutoRedirect = true,
|
AllowAutoRedirect = true,
|
||||||
Encoding = _encoding
|
Encoding = _encoding
|
||||||
};
|
};
|
||||||
@@ -423,7 +424,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
var requestBuilder = new HttpRequestBuilder(submitUrl.ToString())
|
var requestBuilder = new HttpRequestBuilder(submitUrl.ToString())
|
||||||
{
|
{
|
||||||
LogResponseContent = true,
|
LogResponseContent = true,
|
||||||
Method = HttpMethod.POST,
|
Method = HttpMethod.Post,
|
||||||
AllowAutoRedirect = true,
|
AllowAutoRedirect = true,
|
||||||
SuppressHttpError = true,
|
SuppressHttpError = true,
|
||||||
Encoding = _encoding
|
Encoding = _encoding
|
||||||
@@ -466,7 +467,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
var requestBuilder = new HttpRequestBuilder(loginUrl)
|
var requestBuilder = new HttpRequestBuilder(loginUrl)
|
||||||
{
|
{
|
||||||
LogResponseContent = true,
|
LogResponseContent = true,
|
||||||
Method = HttpMethod.GET,
|
Method = HttpMethod.Get,
|
||||||
SuppressHttpError = true,
|
SuppressHttpError = true,
|
||||||
Encoding = _encoding
|
Encoding = _encoding
|
||||||
};
|
};
|
||||||
@@ -491,7 +492,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
var requestBuilder = new HttpRequestBuilder(loginUrl)
|
var requestBuilder = new HttpRequestBuilder(loginUrl)
|
||||||
{
|
{
|
||||||
LogResponseContent = true,
|
LogResponseContent = true,
|
||||||
Method = HttpMethod.GET,
|
Method = HttpMethod.Get,
|
||||||
SuppressHttpError = true,
|
SuppressHttpError = true,
|
||||||
Encoding = _encoding
|
Encoding = _encoding
|
||||||
};
|
};
|
||||||
@@ -565,7 +566,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
var requestBuilder = new HttpRequestBuilder(loginUrl.AbsoluteUri)
|
var requestBuilder = new HttpRequestBuilder(loginUrl.AbsoluteUri)
|
||||||
{
|
{
|
||||||
LogResponseContent = true,
|
LogResponseContent = true,
|
||||||
Method = HttpMethod.GET,
|
Method = HttpMethod.Get,
|
||||||
Encoding = _encoding
|
Encoding = _encoding
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -666,21 +667,21 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
Dictionary<string, string> pairs = null;
|
Dictionary<string, string> pairs = null;
|
||||||
var queryCollection = new NameValueCollection();
|
var queryCollection = new NameValueCollection();
|
||||||
|
|
||||||
var method = HttpMethod.GET;
|
var method = HttpMethod.Get;
|
||||||
if (string.Equals(request.Method, "post", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(request.Method, "post", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
method = HttpMethod.POST;
|
method = HttpMethod.Post;
|
||||||
pairs = new Dictionary<string, string>();
|
pairs = new Dictionary<string, string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var input in request.Inputs)
|
foreach (var input in request.Inputs)
|
||||||
{
|
{
|
||||||
var value = ApplyGoTemplateText(input.Value, variables);
|
var value = ApplyGoTemplateText(input.Value, variables);
|
||||||
if (method == HttpMethod.GET)
|
if (method == HttpMethod.Get)
|
||||||
{
|
{
|
||||||
queryCollection.Add(input.Key, value);
|
queryCollection.Add(input.Key, value);
|
||||||
}
|
}
|
||||||
else if (method == HttpMethod.POST)
|
else if (method == HttpMethod.Post)
|
||||||
{
|
{
|
||||||
pairs.Add(input.Key, value);
|
pairs.Add(input.Key, value);
|
||||||
}
|
}
|
||||||
@@ -707,7 +708,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
httpRequest.Method = method;
|
httpRequest.Method = method;
|
||||||
|
|
||||||
// Add form data for POST requests
|
// Add form data for POST requests
|
||||||
if (method == HttpMethod.POST)
|
if (method == HttpMethod.Post)
|
||||||
{
|
{
|
||||||
foreach (var param in pairs)
|
foreach (var param in pairs)
|
||||||
{
|
{
|
||||||
@@ -724,7 +725,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
public async Task<HttpRequest> DownloadRequest(Uri link)
|
public async Task<HttpRequest> DownloadRequest(Uri link)
|
||||||
{
|
{
|
||||||
Cookies = GetCookies();
|
Cookies = GetCookies();
|
||||||
var method = HttpMethod.GET;
|
var method = HttpMethod.Get;
|
||||||
var headers = new Dictionary<string, string>();
|
var headers = new Dictionary<string, string>();
|
||||||
|
|
||||||
var variables = GetBaseTemplateVariables();
|
var variables = GetBaseTemplateVariables();
|
||||||
@@ -759,7 +760,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
|
|
||||||
if (download.Method == "post")
|
if (download.Method == "post")
|
||||||
{
|
{
|
||||||
method = HttpMethod.POST;
|
method = HttpMethod.Post;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (download.Infohash != null)
|
if (download.Infohash != null)
|
||||||
@@ -1014,11 +1015,11 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
// HttpUtility.UrlPathEncode seems to only encode spaces, we use UrlEncode and replace + with %20 as a workaround
|
// HttpUtility.UrlPathEncode seems to only encode spaces, we use UrlEncode and replace + with %20 as a workaround
|
||||||
var searchUrl = ResolvePath(ApplyGoTemplateText(searchPath.Path, variables, WebUtility.UrlEncode).Replace("+", "%20")).AbsoluteUri;
|
var searchUrl = ResolvePath(ApplyGoTemplateText(searchPath.Path, variables, WebUtility.UrlEncode).Replace("+", "%20")).AbsoluteUri;
|
||||||
var queryCollection = new List<KeyValuePair<string, string>>();
|
var queryCollection = new List<KeyValuePair<string, string>>();
|
||||||
var method = HttpMethod.GET;
|
var method = HttpMethod.Get;
|
||||||
|
|
||||||
if (string.Equals(searchPath.Method, "post", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(searchPath.Method, "post", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
method = HttpMethod.POST;
|
method = HttpMethod.Post;
|
||||||
}
|
}
|
||||||
|
|
||||||
var inputsList = new List<Dictionary<string, string>>();
|
var inputsList = new List<Dictionary<string, string>>();
|
||||||
@@ -1064,7 +1065,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method == HttpMethod.GET)
|
if (method == HttpMethod.Get)
|
||||||
{
|
{
|
||||||
if (queryCollection.Count > 0)
|
if (queryCollection.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -1079,7 +1080,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
|
|||||||
requestbuilder.Method = method;
|
requestbuilder.Method = method;
|
||||||
|
|
||||||
// Add FormData for searchs that POST
|
// Add FormData for searchs that POST
|
||||||
if (method == HttpMethod.POST)
|
if (method == HttpMethod.Post)
|
||||||
{
|
{
|
||||||
foreach (var param in queryCollection)
|
foreach (var param in queryCollection)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
public class DanishBytes : TorrentIndexerBase<DanishBytesSettings>
|
public class DanishBytes : TorrentIndexerBase<DanishBytesSettings>
|
||||||
{
|
{
|
||||||
public override string Name => "DanishBytes";
|
public override string Name => "DanishBytes";
|
||||||
public override string[] IndexerUrls => new string[] { "https://danishbytes.club/" };
|
public override string[] IndexerUrls => new string[] { "https://danishbytes.club/", "https://danishbytes2.org/" };
|
||||||
public override string Description => "DanishBytes is a Private Danish Tracker";
|
public override string Description => "DanishBytes is a Private Danish Tracker";
|
||||||
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
|
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
|
||||||
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
|
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
@@ -56,7 +57,7 @@ namespace NzbDrone.Core.Indexers.Gazelle
|
|||||||
LogResponseContent = true
|
LogResponseContent = true
|
||||||
};
|
};
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
|
|
||||||
var cookies = Cookies;
|
var cookies = Cookies;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
@@ -50,7 +51,7 @@ namespace NzbDrone.Core.Indexers.HDBits
|
|||||||
.Resource("/api/torrents")
|
.Resource("/api/torrents")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
request.Method = HttpMethod.POST;
|
request.Method = HttpMethod.Post;
|
||||||
const string appJson = "application/json";
|
const string appJson = "application/json";
|
||||||
request.Headers.Accept = appJson;
|
request.Headers.Accept = appJson;
|
||||||
request.Headers.ContentType = appJson;
|
request.Headers.ContentType = appJson;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -57,7 +58,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
AllowAutoRedirect = true
|
AllowAutoRedirect = true
|
||||||
};
|
};
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
|
|
||||||
var cookies = Cookies;
|
var cookies = Cookies;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AngleSharp.Html.Parser;
|
using AngleSharp.Html.Parser;
|
||||||
@@ -52,7 +53,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
LogResponseContent = true
|
LogResponseContent = true
|
||||||
};
|
};
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
|
|
||||||
var cookies = Cookies;
|
var cookies = Cookies;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AngleSharp.Html.Parser;
|
using AngleSharp.Html.Parser;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
@@ -54,7 +55,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
LogResponseContent = true
|
LogResponseContent = true
|
||||||
};
|
};
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
|
|
||||||
var cookies = Cookies;
|
var cookies = Cookies;
|
||||||
|
|||||||
341
src/NzbDrone.Core/Indexers/Definitions/MoreThanTV.cs
Normal file
341
src/NzbDrone.Core/Indexers/Definitions/MoreThanTV.cs
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Web;
|
||||||
|
using AngleSharp.Dom;
|
||||||
|
using AngleSharp.Html.Dom;
|
||||||
|
using AngleSharp.Html.Parser;
|
||||||
|
using FluentValidation;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
|
using NzbDrone.Core.Annotations;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Parser;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Indexers.Definitions;
|
||||||
|
|
||||||
|
public class MoreThanTV : TorrentIndexerBase<MoreThanTVSettings>
|
||||||
|
{
|
||||||
|
public override string Name => "MoreThanTV";
|
||||||
|
public override string[] IndexerUrls => new[] { "https://www.morethantv.me/" };
|
||||||
|
public override string Description => "Private torrent tracker for TV / MOVIES";
|
||||||
|
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
|
||||||
|
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
|
||||||
|
public override IndexerCapabilities Capabilities => SetCapabilities();
|
||||||
|
public override bool FollowRedirect => true;
|
||||||
|
|
||||||
|
public MoreThanTV(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
|
||||||
|
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IIndexerRequestGenerator GetRequestGenerator()
|
||||||
|
=> new MoreThanTVRequestGenerator(Settings, Capabilities);
|
||||||
|
|
||||||
|
public override IParseIndexerResponse GetParser()
|
||||||
|
=> new MoreThanTVParser
|
||||||
|
{
|
||||||
|
Settings = Settings
|
||||||
|
};
|
||||||
|
|
||||||
|
private IndexerCapabilities SetCapabilities()
|
||||||
|
{
|
||||||
|
var caps = new IndexerCapabilities
|
||||||
|
{
|
||||||
|
TvSearchParams = new List<TvSearchParam>
|
||||||
|
{
|
||||||
|
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep
|
||||||
|
},
|
||||||
|
MovieSearchParams = new List<MovieSearchParam>
|
||||||
|
{
|
||||||
|
MovieSearchParam.Q
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.Movies, "Movies");
|
||||||
|
caps.Categories.AddCategoryMapping(2, NewznabStandardCategory.TV, "TV");
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IDictionary<string, string> GetCookies()
|
||||||
|
{
|
||||||
|
return CookieUtil.CookieHeaderToDictionary(Settings.Cookie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MoreThanTVRequestGenerator : IIndexerRequestGenerator
|
||||||
|
{
|
||||||
|
private MoreThanTVSettings Settings { get; }
|
||||||
|
private IndexerCapabilities Capabilities { get; }
|
||||||
|
|
||||||
|
private NameValueCollection BrowserHeaders { get; }
|
||||||
|
|
||||||
|
public MoreThanTVRequestGenerator(MoreThanTVSettings settings, IndexerCapabilities capabilities)
|
||||||
|
{
|
||||||
|
Settings = settings;
|
||||||
|
Capabilities = capabilities;
|
||||||
|
BrowserHeaders = new NameValueCollection()
|
||||||
|
{
|
||||||
|
{ "referer", settings.BaseUrl },
|
||||||
|
{ "Upgrade-Insecure-Requests", "1" },
|
||||||
|
{ "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
||||||
|
=> PerformRequest(searchCriteria);
|
||||||
|
|
||||||
|
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
|
||||||
|
=> PerformRequest(searchCriteria);
|
||||||
|
|
||||||
|
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
|
||||||
|
=> PerformRequest(searchCriteria);
|
||||||
|
|
||||||
|
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
|
||||||
|
=> PerformRequest(searchCriteria);
|
||||||
|
|
||||||
|
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
|
||||||
|
=> PerformRequest(searchCriteria);
|
||||||
|
|
||||||
|
public Func<IDictionary<string, string>> GetCookies { get; set; }
|
||||||
|
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||||
|
|
||||||
|
private IndexerPageableRequestChain PerformRequest(SearchCriteriaBase query)
|
||||||
|
{
|
||||||
|
var chain = new IndexerPageableRequestChain();
|
||||||
|
|
||||||
|
var requests = new List<IndexerRequest> { new (new HttpRequest(GetTorrentSearchUrl(query)) { Headers = new HttpHeader(BrowserHeaders), AllowAutoRedirect = true }) };
|
||||||
|
|
||||||
|
if (query is TvSearchCriteria tvSearchCriteria)
|
||||||
|
{
|
||||||
|
// Always search for torrent groups (complete seasons) too
|
||||||
|
var seasonRegex = new Regex(@".*\s[Ss]{1}\d{2}([Ee]{1}\d{2,3})?$", RegexOptions.Compiled);
|
||||||
|
var seasonMatch = seasonRegex.Match(query.SanitizedSearchTerm);
|
||||||
|
if (seasonMatch.Success)
|
||||||
|
{
|
||||||
|
var seasonReplaceRegex = new Regex(@"[Ss]{1}\d{2}([Ee]{1}\d{2,3})?", RegexOptions.Compiled);
|
||||||
|
var newSearchQuery = seasonReplaceRegex.Replace(query.SanitizedSearchTerm, $"Season {tvSearchCriteria.Season}");
|
||||||
|
requests.Add(new IndexerRequest(new HttpRequest(GetTorrentSearchUrl(query, newSearchQuery)) { Headers = new HttpHeader(BrowserHeaders), AllowAutoRedirect = true }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chain.Add(requests);
|
||||||
|
|
||||||
|
return chain;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetTorrentSearchUrl(SearchCriteriaBase query, string overrideSearchTerm = null)
|
||||||
|
{
|
||||||
|
var qc = new NameValueCollection
|
||||||
|
{
|
||||||
|
{ "action", "advanced" },
|
||||||
|
{ "sizetype", "gb" },
|
||||||
|
{ "sizerange", "0.01" },
|
||||||
|
{ "title", overrideSearchTerm ?? GetSearchString(query.SanitizedSearchTerm) }
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (query)
|
||||||
|
{
|
||||||
|
case MovieSearchCriteria:
|
||||||
|
qc.Add("filter_cat[1]", "1"); // HD Movies
|
||||||
|
qc.Add("filter_cat[2]", "1"); // SD Movies
|
||||||
|
break;
|
||||||
|
case TvSearchCriteria:
|
||||||
|
qc.Add("filter_cat[3]", "1"); // HD EPISODE
|
||||||
|
qc.Add("filter_cat[4]", "1"); // SD Episode
|
||||||
|
qc.Add("filter_cat[5]", "1"); // HD Season
|
||||||
|
qc.Add("filter_cat[6]", "1"); // SD Season
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{Settings.BaseUrl}torrents.php?{qc.GetQueryString()}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetSearchString(string input)
|
||||||
|
{
|
||||||
|
input = input.Replace("Marvels", "Marvel"); // strip 's for better results
|
||||||
|
var regex = new Regex(@"(S\d{2})$", RegexOptions.Compiled);
|
||||||
|
return regex.Replace(input, "$1*"); // If we're just seaching for a season (no episode) append an * to include all episodes of that season.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MoreThanTVParser : IParseIndexerResponse
|
||||||
|
{
|
||||||
|
public MoreThanTVSettings Settings { get; init; }
|
||||||
|
|
||||||
|
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||||
|
{
|
||||||
|
var releases = new List<ReleaseInfo>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var parser = new HtmlParser();
|
||||||
|
var document = parser.ParseDocument(indexerResponse.Content);
|
||||||
|
var torrents = document.QuerySelectorAll("#torrent_table > tbody > tr.torrent");
|
||||||
|
var movies = new[] { "movie" };
|
||||||
|
var tv = new[] { "season", "episode" };
|
||||||
|
|
||||||
|
// Loop through all torrents checking for groups
|
||||||
|
foreach (var torrent in torrents)
|
||||||
|
{
|
||||||
|
// Parse required data
|
||||||
|
var torrentGroup = torrent.QuerySelectorAll("table a[href^=\"/torrents.php?action=download\"]");
|
||||||
|
foreach (var downloadAnchor in torrentGroup)
|
||||||
|
{
|
||||||
|
var title = downloadAnchor.ParentElement.ParentElement.ParentElement.TextContent.Trim();
|
||||||
|
title = CleanUpTitle(title);
|
||||||
|
|
||||||
|
var category = torrent.QuerySelector(".cats_col div").GetAttribute("title");
|
||||||
|
|
||||||
|
// default to Other
|
||||||
|
var indexerCategory = NewznabStandardCategory.Other;
|
||||||
|
|
||||||
|
if (movies.Any(category.Contains))
|
||||||
|
{
|
||||||
|
indexerCategory = NewznabStandardCategory.Movies;
|
||||||
|
}
|
||||||
|
else if (tv.Any(category.Contains))
|
||||||
|
{
|
||||||
|
indexerCategory = NewznabStandardCategory.TV;
|
||||||
|
}
|
||||||
|
|
||||||
|
releases.Add(GetReleaseInfo(torrent, downloadAnchor, title, indexerCategory));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return releases;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception("Error while parsing torrent response", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gather Release info from torrent table. Target using css
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="row"></param>
|
||||||
|
/// <param name="downloadAnchor"></param>
|
||||||
|
/// <param name="title"></param>
|
||||||
|
/// <param name="category"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private ReleaseInfo GetReleaseInfo(IElement row, IElement downloadAnchor, string title, IndexerCategory category)
|
||||||
|
{
|
||||||
|
// count from bottom
|
||||||
|
const int FILES_COL = 8;
|
||||||
|
/*const int COMMENTS_COL = 7;*/
|
||||||
|
const int DATE_COL = 6;
|
||||||
|
const int FILESIZE_COL = 5;
|
||||||
|
const int SNATCHED_COL = 4;
|
||||||
|
const int SEEDS_COL = 3;
|
||||||
|
const int LEECHERS_COL = 2;
|
||||||
|
/*const int USER_COL = 1;*/
|
||||||
|
|
||||||
|
var downloadAnchorHref = (downloadAnchor as IHtmlAnchorElement).Href;
|
||||||
|
var queryParams = HttpUtility.ParseQueryString(downloadAnchorHref, Encoding.UTF8);
|
||||||
|
var torrentId = queryParams["id"];
|
||||||
|
|
||||||
|
var qFiles = row.QuerySelector("td:nth-last-child(" + FILES_COL + ")").TextContent;
|
||||||
|
|
||||||
|
var fileCount = ParseUtil.CoerceInt(qFiles);
|
||||||
|
var qPublishDate = row.QuerySelector("td:nth-last-child(" + DATE_COL + ") .time").Attributes["title"].Value;
|
||||||
|
var publishDate = DateTime.ParseExact(qPublishDate, "MMM dd yyyy, HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToLocalTime();
|
||||||
|
var qPoster = row.QuerySelector("div.tp-banner img")?.GetAttribute("src");
|
||||||
|
var poster = (qPoster != null && !qPoster.Contains("caticons")) ? qPoster : null;
|
||||||
|
var description = row.QuerySelector("div.tags")?.TextContent.Trim();
|
||||||
|
var fileSize = row.QuerySelector("td:nth-last-child(" + FILESIZE_COL + ")").TextContent.Trim();
|
||||||
|
var snatched = row.QuerySelector("td:nth-last-child(" + SNATCHED_COL + ")").TextContent.Trim();
|
||||||
|
var seeds = row.QuerySelector("td:nth-last-child(" + SEEDS_COL + ")").TextContent.Trim();
|
||||||
|
var leechs = row.QuerySelector("td:nth-last-child(" + LEECHERS_COL + ")").TextContent.Trim();
|
||||||
|
|
||||||
|
if (fileSize.Length <= 0 || snatched.Length <= 0 || seeds.Length <= 0 || leechs.Length <= 0)
|
||||||
|
{
|
||||||
|
// Size (xx.xx GB[ (Max)]) Snatches (xx) Seeders (xx) Leechers (xx)
|
||||||
|
throw new Exception($"We expected 4 torrent datas.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var detailUrl = $"{Settings.BaseUrl}details.php";
|
||||||
|
|
||||||
|
var size = ParseUtil.GetBytes(fileSize);
|
||||||
|
var grabs = int.Parse(snatched, NumberStyles.AllowThousands, CultureInfo.InvariantCulture);
|
||||||
|
var seeders = int.Parse(seeds, NumberStyles.AllowThousands, CultureInfo.InvariantCulture);
|
||||||
|
var leechers = int.Parse(leechs, NumberStyles.AllowThousands, CultureInfo.InvariantCulture);
|
||||||
|
var detailsUrl = $"{detailUrl}?torrentid={torrentId}";
|
||||||
|
var downloadUrl = $"{detailUrl}?action=download&id={torrentId}";
|
||||||
|
var categories = new List<IndexerCategory> { category };
|
||||||
|
|
||||||
|
return new TorrentInfo
|
||||||
|
{
|
||||||
|
Title = title,
|
||||||
|
Categories = categories,
|
||||||
|
DownloadUrl = downloadUrl,
|
||||||
|
PublishDate = publishDate,
|
||||||
|
PosterUrl = poster,
|
||||||
|
Description = description,
|
||||||
|
Seeders = seeders,
|
||||||
|
Peers = seeders + leechers,
|
||||||
|
Files = fileCount,
|
||||||
|
Size = size,
|
||||||
|
Grabs = grabs,
|
||||||
|
Guid = downloadUrl,
|
||||||
|
InfoUrl = detailsUrl,
|
||||||
|
DownloadVolumeFactor = 0, // ratioless tracker
|
||||||
|
UploadVolumeFactor = 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean Up any title stuff
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string CleanUpTitle(string title)
|
||||||
|
{
|
||||||
|
return title
|
||||||
|
.Replace(".", " ")
|
||||||
|
.Replace("4K", "2160p"); // sonarr cleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MoreThanTVSettingsValidator : AbstractValidator<MoreThanTVSettings>
|
||||||
|
{
|
||||||
|
public MoreThanTVSettingsValidator()
|
||||||
|
{
|
||||||
|
RuleFor(c => c.Cookie).NotEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MoreThanTVSettings : IIndexerSettings
|
||||||
|
{
|
||||||
|
private static readonly MoreThanTVSettingsValidator Validator = new ();
|
||||||
|
|
||||||
|
public MoreThanTVSettings()
|
||||||
|
{
|
||||||
|
Cookie = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
|
||||||
|
public string BaseUrl { get; set; }
|
||||||
|
|
||||||
|
[FieldDefinition(2, Label = "Cookie", HelpText = "Enter the cookies for the site, just copy everything after 'cookie:' from the request headers to the site", HelpLink = "https://wiki.servarr.com/prowlarr/faq#finding-cookies")]
|
||||||
|
public string Cookie { get; set; }
|
||||||
|
|
||||||
|
[FieldDefinition(3)]
|
||||||
|
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
|
||||||
|
|
||||||
|
public NzbDroneValidationResult Validate()
|
||||||
|
{
|
||||||
|
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -53,7 +54,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
LogResponseContent = true
|
LogResponseContent = true
|
||||||
};
|
};
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
|
|
||||||
var cookies = Cookies;
|
var cookies = Cookies;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -50,7 +51,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
|
|
||||||
var request = new HttpRequest(url, HttpAccept.Rss);
|
var request = new HttpRequest(url, HttpAccept.Rss);
|
||||||
request.AllowAutoRedirect = true;
|
request.AllowAutoRedirect = true;
|
||||||
request.Method = HttpMethod.GET;
|
request.Method = HttpMethod.Get;
|
||||||
|
|
||||||
HttpResponse response;
|
HttpResponse response;
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -79,7 +80,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
{
|
{
|
||||||
LogResponseContent = true,
|
LogResponseContent = true,
|
||||||
AllowAutoRedirect = true,
|
AllowAutoRedirect = true,
|
||||||
Method = HttpMethod.POST
|
Method = HttpMethod.Post
|
||||||
};
|
};
|
||||||
|
|
||||||
var authLoginCheckRequest = requestBuilder3
|
var authLoginCheckRequest = requestBuilder3
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -28,7 +29,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
public override string Language => "ru-ru";
|
public override string Language => "ru-ru";
|
||||||
public override Encoding Encoding => Encoding.GetEncoding("windows-1251");
|
public override Encoding Encoding => Encoding.GetEncoding("windows-1251");
|
||||||
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
|
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
|
||||||
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
|
public override IndexerPrivacy Privacy => IndexerPrivacy.SemiPrivate;
|
||||||
public override IndexerCapabilities Capabilities => SetCapabilities();
|
public override IndexerCapabilities Capabilities => SetCapabilities();
|
||||||
|
|
||||||
public PornoLab(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
|
public PornoLab(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
|
||||||
@@ -52,7 +53,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
{
|
{
|
||||||
LogResponseContent = true,
|
LogResponseContent = true,
|
||||||
AllowAutoRedirect = true,
|
AllowAutoRedirect = true,
|
||||||
Method = HttpMethod.POST
|
Method = HttpMethod.Post
|
||||||
};
|
};
|
||||||
|
|
||||||
var authLoginRequest = requestBuilder
|
var authLoginRequest = requestBuilder
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -59,7 +60,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
|
|
||||||
var loginPage = await ExecuteAuth(new HttpRequest(Settings.BaseUrl + "login.php"));
|
var loginPage = await ExecuteAuth(new HttpRequest(Settings.BaseUrl + "login.php"));
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
requestBuilder.SetCookies(loginPage.GetCookies());
|
requestBuilder.SetCookies(loginPage.GetCookies());
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AngleSharp.Html.Parser;
|
using AngleSharp.Html.Parser;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
@@ -58,7 +59,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
|
|
||||||
var loginPage = await ExecuteAuth(new HttpRequest(Settings.BaseUrl + "login.php"));
|
var loginPage = await ExecuteAuth(new HttpRequest(Settings.BaseUrl + "login.php"));
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
requestBuilder.SetCookies(loginPage.GetCookies());
|
requestBuilder.SetCookies(loginPage.GetCookies());
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -31,7 +32,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
public override string Language => "ru-org";
|
public override string Language => "ru-org";
|
||||||
public override Encoding Encoding => Encoding.GetEncoding("windows-1251");
|
public override Encoding Encoding => Encoding.GetEncoding("windows-1251");
|
||||||
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
|
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
|
||||||
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
|
public override IndexerPrivacy Privacy => IndexerPrivacy.SemiPrivate;
|
||||||
public override IndexerCapabilities Capabilities => SetCapabilities();
|
public override IndexerCapabilities Capabilities => SetCapabilities();
|
||||||
|
|
||||||
public RuTracker(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
|
public RuTracker(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
|
||||||
@@ -57,7 +58,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
AllowAutoRedirect = true
|
AllowAutoRedirect = true
|
||||||
};
|
};
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
|
|
||||||
var cookies = Cookies;
|
var cookies = Cookies;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Net.Mime;
|
using System.Net.Mime;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -75,7 +76,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
{
|
{
|
||||||
LogResponseContent = true,
|
LogResponseContent = true,
|
||||||
AllowAutoRedirect = true,
|
AllowAutoRedirect = true,
|
||||||
Method = HttpMethod.POST,
|
Method = HttpMethod.Post,
|
||||||
};
|
};
|
||||||
|
|
||||||
var request = requestBuilder.Build();
|
var request = requestBuilder.Build();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -57,7 +58,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
{
|
{
|
||||||
var requestBuilder = new HttpRequestBuilder(string.Format("{0}/{1}", Settings.BaseUrl.TrimEnd('/'), "checkpoint/API"))
|
var requestBuilder = new HttpRequestBuilder(string.Format("{0}/{1}", Settings.BaseUrl.TrimEnd('/'), "checkpoint/API"))
|
||||||
{
|
{
|
||||||
Method = HttpMethod.POST,
|
Method = HttpMethod.Post,
|
||||||
LogResponseContent = true,
|
LogResponseContent = true,
|
||||||
AllowAutoRedirect = true
|
AllowAutoRedirect = true
|
||||||
};
|
};
|
||||||
@@ -77,7 +78,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
|
|
||||||
var requestBuilder2 = new HttpRequestBuilder(string.Format("{0}/{1}", Settings.BaseUrl.TrimEnd('/'), "checkpoint/"))
|
var requestBuilder2 = new HttpRequestBuilder(string.Format("{0}/{1}", Settings.BaseUrl.TrimEnd('/'), "checkpoint/"))
|
||||||
{
|
{
|
||||||
Method = HttpMethod.POST,
|
Method = HttpMethod.Post,
|
||||||
LogResponseContent = true,
|
LogResponseContent = true,
|
||||||
AllowAutoRedirect = true
|
AllowAutoRedirect = true
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -59,7 +60,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
AllowAutoRedirect = true
|
AllowAutoRedirect = true
|
||||||
};
|
};
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
|
|
||||||
var cookies = Cookies;
|
var cookies = Cookies;
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
@@ -54,7 +55,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
LogResponseContent = true
|
LogResponseContent = true
|
||||||
};
|
};
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
|
|
||||||
var cookies = Cookies;
|
var cookies = Cookies;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AngleSharp.Html.Parser;
|
using AngleSharp.Html.Parser;
|
||||||
@@ -63,7 +64,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
var json1 = JObject.Parse(loginPage.Content);
|
var json1 = JObject.Parse(loginPage.Content);
|
||||||
var captchaSelection = json1["images"][0]["hash"];
|
var captchaSelection = json1["images"][0]["hash"];
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
requestBuilder.SetCookies(loginPage.GetCookies());
|
requestBuilder.SetCookies(loginPage.GetCookies());
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
@@ -79,7 +80,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
LogResponseContent = true
|
LogResponseContent = true
|
||||||
};
|
};
|
||||||
|
|
||||||
requestBuilder.Method = HttpMethod.POST;
|
requestBuilder.Method = HttpMethod.Post;
|
||||||
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
requestBuilder.SetCookies(loginPage.GetCookies());
|
requestBuilder.SetCookies(loginPage.GetCookies());
|
||||||
|
|
||||||
@@ -102,7 +103,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
|||||||
LogResponseContent = true
|
LogResponseContent = true
|
||||||
};
|
};
|
||||||
|
|
||||||
requestBuilder2.Method = HttpMethod.POST;
|
requestBuilder2.Method = HttpMethod.Post;
|
||||||
requestBuilder2.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
requestBuilder2.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
|
||||||
requestBuilder2.SetCookies(response.GetCookies());
|
requestBuilder2.SetCookies(response.GetCookies());
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Indexers.Cardigann;
|
using NzbDrone.Core.Indexers.Cardigann;
|
||||||
using NzbDrone.Core.Indexers.Newznab;
|
using NzbDrone.Core.Indexers.Newznab;
|
||||||
using NzbDrone.Core.IndexerVersions;
|
using NzbDrone.Core.IndexerVersions;
|
||||||
@@ -45,16 +46,27 @@ namespace NzbDrone.Core.Indexers
|
|||||||
public override List<IndexerDefinition> All()
|
public override List<IndexerDefinition> All()
|
||||||
{
|
{
|
||||||
var definitions = base.All();
|
var definitions = base.All();
|
||||||
|
var filteredDefinitions = new List<IndexerDefinition>();
|
||||||
|
|
||||||
foreach (var definition in definitions)
|
foreach (var definition in definitions)
|
||||||
{
|
{
|
||||||
if (definition.Implementation == typeof(Cardigann.Cardigann).Name)
|
if (definition.Implementation == typeof(Cardigann.Cardigann).Name)
|
||||||
{
|
{
|
||||||
MapCardigannDefinition(definition);
|
try
|
||||||
|
{
|
||||||
|
MapCardigannDefinition(definition);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Skip indexer if we fail in Cardigann mapping
|
||||||
|
_logger.Debug("Indexer {0} has no definition", definition.Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filteredDefinitions.Add(definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
return definitions;
|
return filteredDefinitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IndexerDefinition Get(int id)
|
public override IndexerDefinition Get(int id)
|
||||||
@@ -63,7 +75,14 @@ namespace NzbDrone.Core.Indexers
|
|||||||
|
|
||||||
if (definition.Implementation == typeof(Cardigann.Cardigann).Name)
|
if (definition.Implementation == typeof(Cardigann.Cardigann).Name)
|
||||||
{
|
{
|
||||||
MapCardigannDefinition(definition);
|
try
|
||||||
|
{
|
||||||
|
MapCardigannDefinition(definition);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw new ModelNotFoundException(typeof(IndexerDefinition), id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return definition;
|
return definition;
|
||||||
@@ -77,7 +96,7 @@ namespace NzbDrone.Core.Indexers
|
|||||||
private void MapCardigannDefinition(IndexerDefinition definition)
|
private void MapCardigannDefinition(IndexerDefinition definition)
|
||||||
{
|
{
|
||||||
var settings = (CardigannSettings)definition.Settings;
|
var settings = (CardigannSettings)definition.Settings;
|
||||||
var defFile = _definitionService.GetDefinition(settings.DefinitionFile);
|
var defFile = _definitionService.GetCachedDefinition(settings.DefinitionFile);
|
||||||
definition.ExtraFields = defFile.Settings;
|
definition.ExtraFields = defFile.Settings;
|
||||||
|
|
||||||
if (defFile.Login?.Captcha != null && !definition.ExtraFields.Any(x => x.Type == "cardigannCaptcha"))
|
if (defFile.Login?.Captcha != null && !definition.ExtraFields.Any(x => x.Type == "cardigannCaptcha"))
|
||||||
|
|||||||
@@ -28,17 +28,17 @@ namespace NzbDrone.Core.Indexers
|
|||||||
{
|
{
|
||||||
if (indexer.Id > 0 && ((IIndexerSettings)indexer.Settings).BaseSettings.GrabLimit.HasValue)
|
if (indexer.Id > 0 && ((IIndexerSettings)indexer.Settings).BaseSettings.GrabLimit.HasValue)
|
||||||
{
|
{
|
||||||
var grabCount = _historyService.CountSince(indexer.Id, DateTime.Now.StartOfDay(), new List<HistoryEventType> { HistoryEventType.ReleaseGrabbed });
|
var grabCount = _historyService.CountSince(indexer.Id, DateTime.Now.AddHours(-24), new List<HistoryEventType> { HistoryEventType.ReleaseGrabbed });
|
||||||
var grabLimit = ((IIndexerSettings)indexer.Settings).BaseSettings.QueryLimit;
|
var grabLimit = ((IIndexerSettings)indexer.Settings).BaseSettings.GrabLimit;
|
||||||
|
|
||||||
if (grabCount > grabLimit)
|
if (grabCount > grabLimit)
|
||||||
{
|
{
|
||||||
_logger.Info("Indexer {0} has exceeded maximum grab limit for today", indexer.Name);
|
_logger.Info("Indexer {0} has exceeded maximum grab limit for last 24 hours", indexer.Name);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Debug("Indexer {0} has performed {1} of possible {2} grabs for today, proceeding", indexer.Name, grabCount, grabLimit);
|
_logger.Debug("Indexer {0} has performed {1} of possible {2} grabs in last 24 hours, proceeding", indexer.Name, grabCount, grabLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -48,17 +48,17 @@ namespace NzbDrone.Core.Indexers
|
|||||||
{
|
{
|
||||||
if (indexer.Id > 0 && ((IIndexerSettings)indexer.Settings).BaseSettings.QueryLimit.HasValue)
|
if (indexer.Id > 0 && ((IIndexerSettings)indexer.Settings).BaseSettings.QueryLimit.HasValue)
|
||||||
{
|
{
|
||||||
var queryCount = _historyService.CountSince(indexer.Id, DateTime.Now.StartOfDay(), new List<HistoryEventType> { HistoryEventType.IndexerQuery, HistoryEventType.IndexerRss });
|
var queryCount = _historyService.CountSince(indexer.Id, DateTime.Now.AddHours(-24), new List<HistoryEventType> { HistoryEventType.IndexerQuery, HistoryEventType.IndexerRss });
|
||||||
var queryLimit = ((IIndexerSettings)indexer.Settings).BaseSettings.QueryLimit;
|
var queryLimit = ((IIndexerSettings)indexer.Settings).BaseSettings.QueryLimit;
|
||||||
|
|
||||||
if (queryCount > queryLimit)
|
if (queryCount > queryLimit)
|
||||||
{
|
{
|
||||||
_logger.Info("Indexer {0} has exceeded maximum query limit for today", indexer.Name);
|
_logger.Info("Indexer {0} has exceeded maximum query limit for last 24 hours", indexer.Name);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Debug("Indexer {0} has performed {1} of possible {2} queries for today, proceeding", indexer.Name, queryCount, queryLimit);
|
_logger.Debug("Indexer {0} has performed {1} of possible {2} queries in last 24 hours, proceeding", indexer.Name, queryCount, queryLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -128,10 +128,8 @@ namespace NzbDrone.Core.Instrumentation
|
|||||||
private void WriteSqliteLog(Log log, string connectionString)
|
private void WriteSqliteLog(Log log, string connectionString)
|
||||||
{
|
{
|
||||||
using (var connection =
|
using (var connection =
|
||||||
SQLiteFactory.Instance.CreateConnection())
|
new SQLiteConnection(connectionString).OpenAndReturn())
|
||||||
{
|
{
|
||||||
connection.ConnectionString = connectionString;
|
|
||||||
connection.Open();
|
|
||||||
using (var sqlCommand = connection.CreateCommand())
|
using (var sqlCommand = connection.CreateCommand())
|
||||||
{
|
{
|
||||||
sqlCommand.CommandText = INSERT_COMMAND;
|
sqlCommand.CommandText = INSERT_COMMAND;
|
||||||
|
|||||||
@@ -85,6 +85,7 @@
|
|||||||
"CouldNotConnectSignalR": "Could not connect to SignalR, UI won't update",
|
"CouldNotConnectSignalR": "Could not connect to SignalR, UI won't update",
|
||||||
"Custom": "Custom",
|
"Custom": "Custom",
|
||||||
"CustomFilters": "Custom Filters",
|
"CustomFilters": "Custom Filters",
|
||||||
|
"Database": "Database",
|
||||||
"Date": "Date",
|
"Date": "Date",
|
||||||
"Dates": "Dates",
|
"Dates": "Dates",
|
||||||
"DBMigration": "DB Migration",
|
"DBMigration": "DB Migration",
|
||||||
@@ -169,6 +170,7 @@
|
|||||||
"IllRestartLater": "I'll restart later",
|
"IllRestartLater": "I'll restart later",
|
||||||
"IncludeHealthWarningsHelpText": "Include Health Warnings",
|
"IncludeHealthWarningsHelpText": "Include Health Warnings",
|
||||||
"Indexer": "Indexer",
|
"Indexer": "Indexer",
|
||||||
|
"IndexerAlreadySetup": "At least one instace of indexer is already setup",
|
||||||
"IndexerAuth": "Indexer Auth",
|
"IndexerAuth": "Indexer Auth",
|
||||||
"IndexerFlags": "Indexer Flags",
|
"IndexerFlags": "Indexer Flags",
|
||||||
"IndexerHealthCheckNoIndexers": "No indexers enabled, Prowlarr will not return search results",
|
"IndexerHealthCheckNoIndexers": "No indexers enabled, Prowlarr will not return search results",
|
||||||
@@ -176,6 +178,7 @@
|
|||||||
"IndexerLongTermStatusCheckAllClientMessage": "All indexers are unavailable due to failures for more than 6 hours",
|
"IndexerLongTermStatusCheckAllClientMessage": "All indexers are unavailable due to failures for more than 6 hours",
|
||||||
"IndexerLongTermStatusCheckSingleClientMessage": "Indexers unavailable due to failures for more than 6 hours: {0}",
|
"IndexerLongTermStatusCheckSingleClientMessage": "Indexers unavailable due to failures for more than 6 hours: {0}",
|
||||||
"IndexerObsoleteCheckMessage": "Indexers are obsolete or have been updated: {0}. Please remove and (or) re-add to Prowlarr",
|
"IndexerObsoleteCheckMessage": "Indexers are obsolete or have been updated: {0}. Please remove and (or) re-add to Prowlarr",
|
||||||
|
"IndexerNoDefCheckMessage": "Indexers have no definition and will not work: {0}. Please remove and (or) re-add to Prowlarr",
|
||||||
"IndexerPriority": "Indexer Priority",
|
"IndexerPriority": "Indexer Priority",
|
||||||
"IndexerPriorityHelpText": "Indexer Priority from 1 (Highest) to 50 (Lowest). Default: 25.",
|
"IndexerPriorityHelpText": "Indexer Priority from 1 (Highest) to 50 (Lowest). Default: 25.",
|
||||||
"IndexerProxies": "Indexer Proxies",
|
"IndexerProxies": "Indexer Proxies",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Net.Http;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
@@ -29,7 +30,7 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||||||
.Accept(HttpAccept.Json)
|
.Accept(HttpAccept.Json)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
request.Method = HttpMethod.POST;
|
request.Method = HttpMethod.Post;
|
||||||
request.Headers.ContentType = "application/json";
|
request.Headers.ContentType = "application/json";
|
||||||
request.SetContent(payload.ToJson());
|
request.SetContent(payload.ToJson());
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
@@ -27,7 +28,7 @@ namespace NzbDrone.Core.Notifications.Join
|
|||||||
|
|
||||||
public void SendNotification(string title, string message, JoinSettings settings)
|
public void SendNotification(string title, string message, JoinSettings settings)
|
||||||
{
|
{
|
||||||
var method = HttpMethod.GET;
|
var method = HttpMethod.Get;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
@@ -100,7 +101,7 @@ namespace NzbDrone.Core.Notifications.PushBullet
|
|||||||
|
|
||||||
var request = requestBuilder.Build();
|
var request = requestBuilder.Build();
|
||||||
|
|
||||||
request.Method = HttpMethod.GET;
|
request.Method = HttpMethod.Get;
|
||||||
request.AddBasicAuthentication(settings.ApiKey, string.Empty);
|
request.AddBasicAuthentication(settings.ApiKey, string.Empty);
|
||||||
|
|
||||||
var response = _httpClient.Execute(request);
|
var response = _httpClient.Execute(request);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ namespace NzbDrone.Core.Notifications.SendGrid
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings, "mail/send", HttpMethod.POST);
|
var request = BuildRequest(settings, "mail/send", HttpMethod.Post);
|
||||||
|
|
||||||
var payload = new SendGridPayload
|
var payload = new SendGridPayload
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Net.Http;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
@@ -29,7 +30,7 @@ namespace NzbDrone.Core.Notifications.Slack
|
|||||||
.Accept(HttpAccept.Json)
|
.Accept(HttpAccept.Json)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
request.Method = HttpMethod.POST;
|
request.Method = HttpMethod.Post;
|
||||||
request.Headers.ContentType = "application/json";
|
request.Headers.ContentType = "application/json";
|
||||||
request.SetContent(payload.ToJson());
|
request.SetContent(payload.ToJson());
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
|
using System.Net.Http;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Webhook
|
namespace NzbDrone.Core.Notifications.Webhook
|
||||||
{
|
{
|
||||||
public enum WebhookMethod
|
public enum WebhookMethod
|
||||||
{
|
{
|
||||||
POST = HttpMethod.POST,
|
POST = 1,
|
||||||
PUT = HttpMethod.PUT
|
PUT = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
@@ -26,7 +28,13 @@ namespace NzbDrone.Core.Notifications.Webhook
|
|||||||
.Accept(HttpAccept.Json)
|
.Accept(HttpAccept.Json)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
request.Method = (HttpMethod)settings.Method;
|
request.Method = settings.Method switch
|
||||||
|
{
|
||||||
|
(int)WebhookMethod.POST => HttpMethod.Post,
|
||||||
|
(int)WebhookMethod.PUT => HttpMethod.Put,
|
||||||
|
_ => throw new ArgumentOutOfRangeException($"Invalid Webhook method {settings.Method}")
|
||||||
|
};
|
||||||
|
|
||||||
request.Headers.ContentType = "application/json";
|
request.Headers.ContentType = "application/json";
|
||||||
request.SetContent(body.ToJson());
|
request.SetContent(body.ToJson());
|
||||||
|
|
||||||
|
|||||||
@@ -16,14 +16,26 @@ namespace NzbDrone.Core.Parser
|
|||||||
public static string NormalizeMultiSpaces(string s) =>
|
public static string NormalizeMultiSpaces(string s) =>
|
||||||
new Regex(@"\s+").Replace(s.Trim(), " ");
|
new Regex(@"\s+").Replace(s.Trim(), " ");
|
||||||
|
|
||||||
private static string NormalizeNumber(string s)
|
private static string NormalizeNumber(string s, bool isInt = false)
|
||||||
{
|
{
|
||||||
var valStr = new string(s.Where(c => char.IsDigit(c) || c == '.' || c == ',').ToArray());
|
var valStr = new string(s.Where(c => char.IsDigit(c) || c == '.' || c == ',').ToArray());
|
||||||
|
|
||||||
valStr = (valStr.Length == 0) ? "0" : valStr.Replace(",", ".");
|
|
||||||
|
|
||||||
valStr = valStr.Trim().Replace("-", "0");
|
valStr = valStr.Trim().Replace("-", "0");
|
||||||
|
|
||||||
|
if (isInt)
|
||||||
|
{
|
||||||
|
if (valStr.Contains(',') && valStr.Contains('.'))
|
||||||
|
{
|
||||||
|
return valStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
valStr = (valStr.Length == 0) ? "0" : valStr.Replace(".", ",");
|
||||||
|
|
||||||
|
return valStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
valStr = (valStr.Length == 0) ? "0" : valStr.Replace(",", ".");
|
||||||
|
|
||||||
if (valStr.Count(c => c == '.') > 1)
|
if (valStr.Count(c => c == '.') > 1)
|
||||||
{
|
{
|
||||||
var lastOcc = valStr.LastIndexOf('.');
|
var lastOcc = valStr.LastIndexOf('.');
|
||||||
@@ -39,17 +51,17 @@ namespace NzbDrone.Core.Parser
|
|||||||
|
|
||||||
public static float CoerceFloat(string str) => float.Parse(NormalizeNumber(str), NumberStyles.Any, CultureInfo.InvariantCulture);
|
public static float CoerceFloat(string str) => float.Parse(NormalizeNumber(str), NumberStyles.Any, CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
public static int CoerceInt(string str) => int.Parse(NormalizeNumber(str), NumberStyles.Any, CultureInfo.InvariantCulture);
|
public static int CoerceInt(string str) => int.Parse(NormalizeNumber(str, true), NumberStyles.Any, CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
public static long CoerceLong(string str) => long.Parse(NormalizeNumber(str), NumberStyles.Any, CultureInfo.InvariantCulture);
|
public static long CoerceLong(string str) => long.Parse(NormalizeNumber(str, true), NumberStyles.Any, CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
public static bool TryCoerceDouble(string str, out double result) => double.TryParse(NormalizeNumber(str), NumberStyles.Any, CultureInfo.InvariantCulture, out result);
|
public static bool TryCoerceDouble(string str, out double result) => double.TryParse(NormalizeNumber(str), NumberStyles.Any, CultureInfo.InvariantCulture, out result);
|
||||||
|
|
||||||
public static bool TryCoerceFloat(string str, out float result) => float.TryParse(NormalizeNumber(str), NumberStyles.Any, CultureInfo.InvariantCulture, out result);
|
public static bool TryCoerceFloat(string str, out float result) => float.TryParse(NormalizeNumber(str), NumberStyles.Any, CultureInfo.InvariantCulture, out result);
|
||||||
|
|
||||||
public static bool TryCoerceInt(string str, out int result) => int.TryParse(NormalizeNumber(str), NumberStyles.Any, CultureInfo.InvariantCulture, out result);
|
public static bool TryCoerceInt(string str, out int result) => int.TryParse(NormalizeNumber(str, true), NumberStyles.Any, CultureInfo.InvariantCulture, out result);
|
||||||
|
|
||||||
public static bool TryCoerceLong(string str, out long result) => long.TryParse(NormalizeNumber(str), NumberStyles.Any, CultureInfo.InvariantCulture, out result);
|
public static bool TryCoerceLong(string str, out long result) => long.TryParse(NormalizeNumber(str, true), NumberStyles.Any, CultureInfo.InvariantCulture, out result);
|
||||||
|
|
||||||
public static long? GetLongFromString(string str)
|
public static long? GetLongFromString(string str)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Data.SQLite;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
@@ -6,6 +7,7 @@ using NzbDrone.Common.EnvironmentInfo;
|
|||||||
using NzbDrone.Common.Processes;
|
using NzbDrone.Common.Processes;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Lifecycle;
|
using NzbDrone.Core.Lifecycle;
|
||||||
|
using NzbDrone.Core.Messaging;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
|
||||||
namespace NzbDrone.Host
|
namespace NzbDrone.Host
|
||||||
@@ -99,6 +101,7 @@ namespace NzbDrone.Host
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[EventHandleOrder(EventHandleOrder.Last)]
|
||||||
public void Handle(ApplicationShutdownRequested message)
|
public void Handle(ApplicationShutdownRequested message)
|
||||||
{
|
{
|
||||||
if (!_runtimeInfo.IsWindowsService)
|
if (!_runtimeInfo.IsWindowsService)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Data.SQLite;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@@ -99,6 +100,11 @@ namespace NzbDrone.Host
|
|||||||
Logger.Info(e.Message);
|
Logger.Info(e.Message);
|
||||||
LogManager.Configuration = null;
|
LogManager.Configuration = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure there are no lingering database connections
|
||||||
|
GC.Collect();
|
||||||
|
GC.WaitForPendingFinalizers();
|
||||||
|
SQLiteConnection.ClearAllPools();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IHostBuilder CreateConsoleHostBuilder(string[] args, StartupContext context)
|
public static IHostBuilder CreateConsoleHostBuilder(string[] args, StartupContext context)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace Prowlarr.Api.V1.Indexers
|
|||||||
public class IndexerResource : ProviderResource<IndexerResource>
|
public class IndexerResource : ProviderResource<IndexerResource>
|
||||||
{
|
{
|
||||||
public string[] IndexerUrls { get; set; }
|
public string[] IndexerUrls { get; set; }
|
||||||
|
public string DefinitionName { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public string Language { get; set; }
|
public string Language { get; set; }
|
||||||
public string Encoding { get; set; }
|
public string Encoding { get; set; }
|
||||||
@@ -51,6 +52,8 @@ namespace Prowlarr.Api.V1.Indexers
|
|||||||
|
|
||||||
var resource = base.ToResource(definition);
|
var resource = base.ToResource(definition);
|
||||||
|
|
||||||
|
resource.DefinitionName = definition.ImplementationName;
|
||||||
|
|
||||||
var infoLinkName = definition.ImplementationName;
|
var infoLinkName = definition.ImplementationName;
|
||||||
|
|
||||||
if (definition.Implementation == typeof(Cardigann).Name)
|
if (definition.Implementation == typeof(Cardigann).Name)
|
||||||
@@ -71,6 +74,7 @@ namespace Prowlarr.Api.V1.Indexers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource.DefinitionName = settings.DefinitionFile;
|
||||||
infoLinkName = settings.DefinitionFile;
|
infoLinkName = settings.DefinitionFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +114,7 @@ namespace Prowlarr.Api.V1.Indexers
|
|||||||
|
|
||||||
var settings = (CardigannSettings)definition.Settings;
|
var settings = (CardigannSettings)definition.Settings;
|
||||||
|
|
||||||
var cardigannDefinition = _definitionService.GetDefinition(settings.DefinitionFile);
|
var cardigannDefinition = _definitionService.GetCachedDefinition(settings.DefinitionFile);
|
||||||
|
|
||||||
foreach (var field in resource.Fields)
|
foreach (var field in resource.Fields)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -148,11 +148,11 @@ namespace NzbDrone.Api.V1.Indexers
|
|||||||
|
|
||||||
foreach (var result in results.Releases)
|
foreach (var result in results.Releases)
|
||||||
{
|
{
|
||||||
result.DownloadUrl = result.DownloadUrl.IsNotNullOrWhiteSpace() ? _downloadMappingService.ConvertToProxyLink(new Uri(result.DownloadUrl), request.server, indexerDef.Id, result.Title).ToString() : null;
|
result.DownloadUrl = result.DownloadUrl.IsNotNullOrWhiteSpace() ? _downloadMappingService.ConvertToProxyLink(new Uri(result.DownloadUrl), request.server, indexerDef.Id, result.Title).AbsoluteUri : null;
|
||||||
|
|
||||||
if (result.DownloadProtocol == DownloadProtocol.Torrent)
|
if (result.DownloadProtocol == DownloadProtocol.Torrent)
|
||||||
{
|
{
|
||||||
((TorrentInfo)result).MagnetUrl = ((TorrentInfo)result).MagnetUrl.IsNotNullOrWhiteSpace() ? _downloadMappingService.ConvertToProxyLink(new Uri(((TorrentInfo)result).MagnetUrl), request.server, indexerDef.Id, result.Title).ToString() : null;
|
((TorrentInfo)result).MagnetUrl = ((TorrentInfo)result).MagnetUrl.IsNotNullOrWhiteSpace() ? _downloadMappingService.ConvertToProxyLink(new Uri(((TorrentInfo)result).MagnetUrl), request.server, indexerDef.Id, result.Title).AbsoluteUri : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -162,8 +162,8 @@ namespace Prowlarr.Api.V1.Search
|
|||||||
var release = downloadDecision.ToResource();
|
var release = downloadDecision.ToResource();
|
||||||
|
|
||||||
_remoteReleaseCache.Set(GetCacheKey(release), downloadDecision, TimeSpan.FromMinutes(30));
|
_remoteReleaseCache.Set(GetCacheKey(release), downloadDecision, TimeSpan.FromMinutes(30));
|
||||||
release.DownloadUrl = release.DownloadUrl.IsNotNullOrWhiteSpace() ? _downloadMappingService.ConvertToProxyLink(new Uri(release.DownloadUrl), serverUrl, release.IndexerId, release.Title).ToString() : null;
|
release.DownloadUrl = release.DownloadUrl.IsNotNullOrWhiteSpace() ? _downloadMappingService.ConvertToProxyLink(new Uri(release.DownloadUrl), serverUrl, release.IndexerId, release.Title).AbsoluteUri : null;
|
||||||
release.MagnetUrl = release.MagnetUrl.IsNotNullOrWhiteSpace() ? _downloadMappingService.ConvertToProxyLink(new Uri(release.MagnetUrl), serverUrl, release.IndexerId, release.Title).ToString() : null;
|
release.MagnetUrl = release.MagnetUrl.IsNotNullOrWhiteSpace() ? _downloadMappingService.ConvertToProxyLink(new Uri(release.MagnetUrl), serverUrl, release.IndexerId, release.Title).AbsoluteUri : null;
|
||||||
|
|
||||||
result.Add(release);
|
result.Add(release);
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user