Compare commits

..

1 Commits

Author SHA1 Message Date
Qstick
fa304dcaca Random 2022-01-02 23:39:55 -06:00
103 changed files with 369 additions and 1078 deletions

View File

@@ -7,7 +7,7 @@ variables:
outputFolder: './_output'
artifactsFolder: './_artifacts'
testsFolder: './_tests'
majorVersion: '0.2.0'
majorVersion: '0.1.10'
minorVersion: $[counter('minorVersion', 1)]
prowlarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'

View File

@@ -8,7 +8,6 @@ import BoolFilterBuilderRowValue from './BoolFilterBuilderRowValue';
import DateFilterBuilderRowValue from './DateFilterBuilderRowValue';
import FilterBuilderRowValueConnector from './FilterBuilderRowValueConnector';
import IndexerFilterBuilderRowValueConnector from './IndexerFilterBuilderRowValueConnector';
import PrivacyFilterBuilderRowValue from './PrivacyFilterBuilderRowValue';
import ProtocolFilterBuilderRowValue from './ProtocolFilterBuilderRowValue';
import TagFilterBuilderRowValueConnector from './TagFilterBuilderRowValueConnector';
import styles from './FilterBuilderRow.css';
@@ -64,9 +63,6 @@ function getRowValueConnector(selectedFilterBuilderProp) {
case filterBuilderValueTypes.PROTOCOL:
return ProtocolFilterBuilderRowValue;
case filterBuilderValueTypes.PRIVACY:
return PrivacyFilterBuilderRowValue;
case filterBuilderValueTypes.TAG:
return TagFilterBuilderRowValueConnector;

View File

@@ -1,20 +0,0 @@
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;

View File

@@ -4,7 +4,6 @@ export const DATE = 'date';
export const DEFAULT = 'default';
export const INDEXER = 'indexer';
export const PROTOCOL = 'protocol';
export const PRIVACY = 'privacy';
export const APP_PROFILE = 'appProfile';
export const MOVIE_STATUS = 'movieStatus';
export const TAG = 'tag';

View File

@@ -4,7 +4,7 @@ import Modal from 'Components/Modal/Modal';
import AddIndexerModalContentConnector from './AddIndexerModalContentConnector';
import styles from './AddIndexerModal.css';
function AddIndexerModal({ isOpen, onModalClose, onSelectIndexer, ...otherProps }) {
function AddIndexerModal({ isOpen, onModalClose, ...otherProps }) {
return (
<Modal
isOpen={isOpen}
@@ -14,7 +14,6 @@ function AddIndexerModal({ isOpen, onModalClose, onSelectIndexer, ...otherProps
<AddIndexerModalContentConnector
{...otherProps}
onModalClose={onModalClose}
onSelectIndexer={onSelectIndexer}
/>
</Modal>
);
@@ -22,8 +21,7 @@ function AddIndexerModal({ isOpen, onModalClose, onSelectIndexer, ...otherProps
AddIndexerModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onModalClose: PropTypes.func.isRequired,
onSelectIndexer: PropTypes.func.isRequired
onModalClose: PropTypes.func.isRequired
};
export default AddIndexerModal;

View File

@@ -15,7 +15,7 @@ import TableBody from 'Components/Table/TableBody';
import { kinds, scrollDirections } from 'Helpers/Props';
import getErrorMessage from 'Utilities/Object/getErrorMessage';
import translate from 'Utilities/String/translate';
import SelectIndexerRowConnector from './SelectIndexerRowConnector';
import SelectIndexerRow from './SelectIndexerRow';
import styles from './AddIndexerModalContent.css';
const columns = [
@@ -219,7 +219,7 @@ class AddIndexerModalContent extends Component {
<TableBody>
{
filteredIndexers.map((indexer) => (
<SelectIndexerRowConnector
<SelectIndexerRow
key={indexer.name}
implementation={indexer.implementation}
{...indexer}

View File

@@ -51,7 +51,7 @@ class AddIndexerModalContentConnector extends Component {
onIndexerSelect = ({ implementation, name }) => {
this.props.selectIndexerSchema({ implementation, name });
this.props.onSelectIndexer();
this.props.onModalClose({ indexerSelected: true });
};
onSortPress = (sortKey, sortDirection) => {
@@ -76,8 +76,7 @@ AddIndexerModalContentConnector.propTypes = {
fetchIndexerSchema: PropTypes.func.isRequired,
selectIndexerSchema: PropTypes.func.isRequired,
setIndexerSchemaSort: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired,
onSelectIndexer: PropTypes.func.isRequired
onModalClose: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(AddIndexerModalContentConnector);

View File

@@ -3,9 +3,3 @@
width: 32px;
}
.alreadyExistsIcon {
margin-left: 10px;
color: #37bc9b;
pointer-events: all;
}

View File

@@ -1,9 +1,7 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Icon from 'Components/Icon';
import TableRowCell from 'Components/Table/Cells/TableRowCell';
import TableRowButton from 'Components/Table/TableRowButton';
import { icons } from 'Helpers/Props';
import ProtocolLabel from 'Indexer/Index/Table/ProtocolLabel';
import firstCharToUpper from 'Utilities/String/firstCharToUpper';
import translate from 'Utilities/String/translate';
@@ -31,8 +29,7 @@ class SelectIndexerRow extends Component {
protocol,
privacy,
name,
language,
isExistingIndexer
language
} = this.props;
return (
@@ -45,16 +42,6 @@ class SelectIndexerRow extends Component {
<TableRowCell>
{name}
{
isExistingIndexer ?
<Icon
className={styles.alreadyExistsIcon}
name={icons.CHECK_CIRCLE}
size={15}
title={translate('IndexerAlreadySetup')}
/> :
null
}
</TableRowCell>
<TableRowCell>
@@ -75,8 +62,7 @@ SelectIndexerRow.propTypes = {
privacy: PropTypes.string.isRequired,
language: PropTypes.string.isRequired,
implementation: PropTypes.string.isRequired,
onIndexerSelect: PropTypes.func.isRequired,
isExistingIndexer: PropTypes.bool.isRequired
onIndexerSelect: PropTypes.func.isRequired
};
export default SelectIndexerRow;

View File

@@ -1,18 +0,0 @@
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);

View File

@@ -39,7 +39,6 @@ function EditIndexerModalContent(props) {
const {
id,
implementationName,
definitionName,
name,
enable,
redirect,
@@ -51,12 +50,10 @@ function EditIndexerModalContent(props) {
priority
} = item;
const indexerDisplayName = implementationName === definitionName ? implementationName : `${implementationName} (${definitionName})`;
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
{`${id ? translate('EditIndexer') : translate('AddIndexer')} - ${indexerDisplayName}`}
{`${id ? translate('EditIndexer') : translate('AddIndexer')} - ${implementationName}`}
</ModalHeader>
<ModalBody>

View File

@@ -193,12 +193,11 @@ class IndexerIndex extends Component {
this.setState({ isAddIndexerModalOpen: true });
};
onAddIndexerModalClose = () => {
this.setState({ isAddIndexerModalOpen: false });
};
onAddIndexerSelectIndexer = () => {
this.setState({ isEditIndexerModalOpen: true });
onAddIndexerModalClose = ({ indexerSelected = false } = {}) => {
this.setState({
isAddIndexerModalOpen: false,
isEditIndexerModalOpen: indexerSelected
});
};
onEditIndexerModalClose = () => {
@@ -464,7 +463,6 @@ class IndexerIndex extends Component {
<AddIndexerModal
isOpen={isAddIndexerModalOpen}
onModalClose={this.onAddIndexerModalClose}
onSelectIndexer={this.onAddIndexerSelectIndexer}
/>
<EditIndexerModalConnector

View File

@@ -244,15 +244,12 @@ class IndexerIndexRow extends Component {
onPress={this.onIndexerInfoPress}
/>
{
indexerUrls ?
<IconButton
className={styles.externalLink}
name={icons.EXTERNAL_LINK}
title={translate('Website')}
to={indexerUrls[0].replace('api.', '')}
/> : null
}
<IconButton
className={styles.externalLink}
name={icons.EXTERNAL_LINK}
title={translate('Website')}
to={indexerUrls[0].replace('api.', '')}
/>
<IconButton
name={icons.EDIT}
@@ -292,7 +289,7 @@ class IndexerIndexRow extends Component {
IndexerIndexRow.propTypes = {
id: PropTypes.number.isRequired,
indexerUrls: PropTypes.arrayOf(PropTypes.string),
indexerUrls: PropTypes.arrayOf(PropTypes.string).isRequired,
protocol: PropTypes.string.isRequired,
privacy: PropTypes.string.isRequired,
priority: PropTypes.number.isRequired,
@@ -301,7 +298,7 @@ IndexerIndexRow.propTypes = {
redirect: PropTypes.bool.isRequired,
appProfile: PropTypes.object.isRequired,
status: PropTypes.object,
capabilities: PropTypes.object,
capabilities: PropTypes.object.isRequired,
added: PropTypes.string.isRequired,
tags: PropTypes.arrayOf(PropTypes.number).isRequired,
columns: PropTypes.arrayOf(PropTypes.object).isRequired,

View File

@@ -118,12 +118,12 @@ export const defaultState = {
filterBuilderProps: [
{
name: 'name',
label: translate('IndexerName'),
label: 'Indexer Name',
type: filterBuilderTypes.STRING
},
{
name: 'enable',
label: translate('Enabled'),
label: 'Enabled',
type: filterBuilderTypes.EXACT,
valueType: filterBuilderValueTypes.BOOL
},
@@ -135,21 +135,15 @@ export const defaultState = {
},
{
name: 'priority',
label: translate('Priority'),
label: 'Priority',
type: filterBuilderTypes.NUMBER
},
{
name: 'protocol',
label: translate('Protocol'),
label: 'Protocol',
type: filterBuilderTypes.EXACT,
valueType: filterBuilderValueTypes.PROTOCOL
},
{
name: 'privacy',
label: translate('Privacy'),
type: filterBuilderTypes.EXACT,
valueType: filterBuilderValueTypes.PRIVACY
},
{
name: 'appProfileId',
label: translate('AppProfile'),

View File

@@ -80,8 +80,8 @@ export default function createSentryMiddleware() {
return;
}
const dsn = isProduction ? 'https://b233094711fe4430a0b0c5da2e01df93@sentry.servarr.com/28' :
'https://116efebd253a4dff9df9475a31510001@sentry.servarr.com/37';
const dsn = isProduction ? 'https://b0fb75c38ef4487dbf742f79c4ba62d2@sentry.servarr.com/12' :
'https://da610619280249f891ec3ee306906793@sentry.servarr.com/13';
sentry.init({
dsn,

View File

@@ -0,0 +1,14 @@
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;

View File

@@ -1,15 +0,0 @@
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;

View File

@@ -36,12 +36,6 @@ function selectSettings(item, pendingChanges, saveError) {
return result;
}
if (key === 'definitionName') {
result.definitionName = item[key];
return result;
}
const setting = {
value: item[key],
errors: _.map(_.remove(validationFailures, (failure) => {

View File

@@ -82,6 +82,9 @@ namespace NzbDrone.Common.Http.Dispatchers
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.
if (e.Status == WebExceptionStatus.NameResolutionFailure)
{
@@ -239,5 +242,36 @@ 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();
}
}
}
}
}

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using NLog;
using NzbDrone.Common.Cache;
@@ -88,11 +87,13 @@ namespace NzbDrone.Common.Http
// 302 or 303 should default to GET on redirect even if POST on original
if (response.StatusCode == HttpStatusCode.Redirect || response.StatusCode == HttpStatusCode.RedirectMethod)
{
request.Method = HttpMethod.Get;
request.Method = HttpMethod.GET;
request.ContentData = null;
}
response = await ExecuteRequestAsync(request, cookieContainer);
var redirectContainer = HandleRedirectCookies(request, response);
response = await ExecuteRequestAsync(request, redirectContainer);
}
while (response.HasHttpRedirect);
}
@@ -163,6 +164,41 @@ namespace NzbDrone.Common.Http
return response;
}
private CookieContainer HandleRedirectCookies(HttpRequest request, HttpResponse response)
{
var sourceContainer = new CookieContainer();
var responseCookies = response.GetCookies();
if (responseCookies.Count != 0)
{
foreach (var pair in responseCookies)
{
Cookie cookie;
if (pair.Value == null)
{
cookie = new Cookie(pair.Key, "", "/")
{
Expires = DateTime.Now.AddDays(-1)
};
}
else
{
cookie = new Cookie(pair.Key, pair.Value, "/")
{
// Use Now rather than UtcNow to work around Mono cookie expiry bug.
// See https://gist.github.com/ta264/7822b1424f72e5b4c961
Expires = DateTime.Now.AddHours(1)
};
}
sourceContainer.Add((Uri)request.Url, cookie);
}
}
return sourceContainer;
}
private CookieContainer InitializeRequestCookies(HttpRequest request)
{
lock (_cookieContainerCache)
@@ -264,7 +300,7 @@ namespace NzbDrone.Common.Http
public Task<HttpResponse> GetAsync(HttpRequest request)
{
request.Method = HttpMethod.Get;
request.Method = HttpMethod.GET;
return ExecuteAsync(request);
}
@@ -289,7 +325,7 @@ namespace NzbDrone.Common.Http
public Task<HttpResponse> HeadAsync(HttpRequest request)
{
request.Method = HttpMethod.Head;
request.Method = HttpMethod.HEAD;
return ExecuteAsync(request);
}
@@ -300,7 +336,7 @@ namespace NzbDrone.Common.Http
public Task<HttpResponse> PostAsync(HttpRequest request)
{
request.Method = HttpMethod.Post;
request.Method = HttpMethod.POST;
return ExecuteAsync(request);
}

View File

@@ -0,0 +1,14 @@
namespace NzbDrone.Common.Http
{
public enum HttpMethod
{
GET,
POST,
PUT,
DELETE,
HEAD,
OPTIONS,
PATCH,
MERGE
}
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Extensions;
@@ -14,7 +13,6 @@ namespace NzbDrone.Common.Http
{
Url = new HttpUri(url);
Headers = new HttpHeader();
Method = HttpMethod.Get;
ConnectionKeepAlive = true;
AllowAutoRedirect = true;
Cookies = new Dictionary<string, string>();

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using NzbDrone.Common.Extensions;
@@ -38,7 +37,7 @@ namespace NzbDrone.Common.Http
{
BaseUrl = new HttpUri(baseUrl);
ResourceUrl = string.Empty;
Method = HttpMethod.Get;
Method = HttpMethod.GET;
Encoding = Encoding.UTF8;
QueryParams = new List<KeyValuePair<string, string>>();
SuffixQueryParams = new List<KeyValuePair<string, string>>();
@@ -276,7 +275,7 @@ namespace NzbDrone.Common.Http
public virtual HttpRequestBuilder Post()
{
Method = HttpMethod.Post;
Method = HttpMethod.POST;
return this;
}
@@ -398,7 +397,7 @@ namespace NzbDrone.Common.Http
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.");
}
@@ -414,7 +413,7 @@ namespace NzbDrone.Common.Http
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.");
}

View File

@@ -11,21 +11,19 @@ namespace NzbDrone.Common.Http
{
private static readonly Regex RegexSetCookie = new Regex("^(.*?)=(.*?)(?:;|$)", RegexOptions.Compiled);
public HttpResponse(HttpRequest request, HttpHeader headers, CookieCollection cookies, byte[] binaryData, long elapsedTime = 0, HttpStatusCode statusCode = HttpStatusCode.OK)
public HttpResponse(HttpRequest request, HttpHeader headers, byte[] binaryData, long elapsedTime = 0, HttpStatusCode statusCode = HttpStatusCode.OK)
{
Request = request;
Headers = headers;
Cookies = cookies;
ResponseData = binaryData;
StatusCode = statusCode;
ElapsedTime = elapsedTime;
}
public HttpResponse(HttpRequest request, HttpHeader headers, CookieCollection cookies, string content, long elapsedTime = 0, HttpStatusCode statusCode = HttpStatusCode.OK)
public HttpResponse(HttpRequest request, HttpHeader headers, string content, long elapsedTime = 0, HttpStatusCode statusCode = HttpStatusCode.OK)
{
Request = request;
Headers = headers;
Cookies = cookies;
ResponseData = Headers.GetEncodingFromContentType().GetBytes(content);
_content = content;
StatusCode = statusCode;
@@ -34,7 +32,6 @@ namespace NzbDrone.Common.Http
public HttpRequest Request { get; private set; }
public HttpHeader Headers { get; private set; }
public CookieCollection Cookies { get; private set; }
public HttpStatusCode StatusCode { get; private set; }
public long ElapsedTime { get; private set; }
public byte[] ResponseData { get; private set; }
@@ -92,9 +89,14 @@ namespace NzbDrone.Common.Http
{
var result = new Dictionary<string, string>();
foreach (Cookie cookie in Cookies)
var setCookieHeaders = CookieUtil.CookieHeaderToDictionary();
foreach (var cookie in setCookieHeaders)
{
result[cookie.Name] = cookie.Value;
var match = RegexSetCookie.Match(cookie);
if (match.Success)
{
result[match.Groups[1].Value] = match.Groups[2].Value;
}
}
return result;

View File

@@ -1,7 +1,6 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using Newtonsoft.Json;
using NzbDrone.Common.Serializer;
@@ -18,14 +17,14 @@ namespace NzbDrone.Common.Http
public JsonRpcRequestBuilder(string baseUrl)
: base(baseUrl)
{
Method = HttpMethod.Post;
Method = HttpMethod.POST;
JsonParameters = new List<object>();
}
public JsonRpcRequestBuilder(string baseUrl, string method, IEnumerable<object> parameters)
: base(baseUrl)
{
Method = HttpMethod.Post;
Method = HttpMethod.POST;
JsonMethod = method;
JsonParameters = parameters.ToList();
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
@@ -35,7 +34,7 @@ namespace NzbDrone.Core.Test.IndexerTests.AvistazTests
var recentFeed = ReadAllText(@"Files/Indexers/Avistaz/recentfeed.json");
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)));
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;

View File

@@ -1,7 +1,6 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
@@ -35,7 +34,7 @@ namespace NzbDrone.Core.Test.IndexerTests.AvistazTests
var recentFeed = ReadAllText(@"Files/Indexers/PrivateHD/recentfeed.json");
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)));
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;

View File

@@ -1,7 +1,6 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
@@ -34,7 +33,7 @@ namespace NzbDrone.Core.Test.IndexerTests.FileListTests
var recentFeed = ReadAllText(@"Files/Indexers/FileList/recentfeed.json");
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)));
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;

View File

@@ -1,7 +1,6 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
@@ -46,7 +45,7 @@ namespace NzbDrone.Core.Test.IndexerTests.HDBitsTests
var responseJson = ReadAllText(fileName);
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)));
var torrents = (await Subject.Fetch(_movieSearchCriteria)).Releases;

View File

@@ -1,7 +1,6 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
@@ -44,7 +43,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
var recentFeed = ReadAllText(@"Files/Indexers/Newznab/newznab_nzb_su.xml");
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)));
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 }, Limit = 100, Offset = 0 })).Releases;

View File

@@ -1,6 +1,5 @@
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
@@ -38,11 +37,11 @@ namespace NzbDrone.Core.Test.IndexerTests.PTPTests
var responseJson = ReadAllText(fileName);
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())));
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)));
var torrents = (await Subject.Fetch(new MovieSearchCriteria())).Releases;

View File

@@ -1,7 +1,6 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
@@ -40,7 +39,7 @@ namespace NzbDrone.Core.Test.IndexerTests.RarbgTests
var recentFeed = ReadAllText(@"Files/Indexers/Rarbg/RecentFeed_v2.json");
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)));
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
@@ -67,7 +66,7 @@ namespace NzbDrone.Core.Test.IndexerTests.RarbgTests
public async Task should_parse_error_20_as_empty_results()
{
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\" }")));
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;
@@ -79,7 +78,7 @@ namespace NzbDrone.Core.Test.IndexerTests.RarbgTests
public async Task should_warn_on_unknown_error()
{
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\" }")));
var releases = (await Subject.Fetch(new MovieSearchCriteria { Categories = new int[] { 2000 } })).Releases;

View File

@@ -1,7 +1,6 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
@@ -45,7 +44,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorznabTests
var recentFeed = ReadAllText(@"Files/Indexers/Torznab/torznab_hdaccess_net.xml");
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)));
var releases = (await Subject.Fetch(new MovieSearchCriteria())).Releases;
@@ -74,7 +73,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorznabTests
var recentFeed = ReadAllText(@"Files/Indexers/Torznab/torznab_tpb.xml");
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)));
var releases = (await Subject.Fetch(new MovieSearchCriteria())).Releases;
@@ -104,7 +103,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorznabTests
var recentFeed = ReadAllText(@"Files/Indexers/Torznab/torznab_animetosho.xml");
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)));
var releases = (await Subject.Fetch(new MovieSearchCriteria())).Releases;

View File

@@ -30,27 +30,9 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("1", 1)]
[TestCase("11", 11)]
[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)
{
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);
}
}
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using FluentValidation.Results;
using Newtonsoft.Json;
using NLog;
@@ -32,13 +31,13 @@ namespace NzbDrone.Core.Applications.LazyLibrarian
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);
}
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);
@@ -77,7 +76,7 @@ namespace NzbDrone.Core.Applications.LazyLibrarian
{ "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));
}
@@ -93,7 +92,7 @@ namespace NzbDrone.Core.Applications.LazyLibrarian
{ "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));
return indexer;
}
@@ -111,7 +110,7 @@ namespace NzbDrone.Core.Applications.LazyLibrarian
{ "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));
return indexer;
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using FluentValidation.Results;
using Newtonsoft.Json;
using NLog;
@@ -34,13 +33,13 @@ namespace NzbDrone.Core.Applications.Lidarr
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);
}
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);
}
@@ -48,7 +47,7 @@ namespace NzbDrone.Core.Applications.Lidarr
{
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);
}
catch (HttpException ex)
@@ -64,19 +63,19 @@ namespace NzbDrone.Core.Applications.Lidarr
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);
}
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);
}
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());
@@ -85,7 +84,7 @@ namespace NzbDrone.Core.Applications.Lidarr
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());
@@ -94,7 +93,7 @@ namespace NzbDrone.Core.Applications.Lidarr
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());

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using FluentValidation.Results;
using Newtonsoft.Json;
using NLog;
@@ -32,13 +31,13 @@ namespace NzbDrone.Core.Applications.Mylar
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);
}
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);
@@ -77,7 +76,7 @@ namespace NzbDrone.Core.Applications.Mylar
{ "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));
}
@@ -93,7 +92,7 @@ namespace NzbDrone.Core.Applications.Mylar
{ "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));
return indexer;
}
@@ -111,7 +110,7 @@ namespace NzbDrone.Core.Applications.Mylar
{ "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));
return indexer;
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using FluentValidation.Results;
using Newtonsoft.Json;
using NLog;
@@ -34,13 +33,13 @@ namespace NzbDrone.Core.Applications.Radarr
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);
}
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);
}
@@ -48,7 +47,7 @@ namespace NzbDrone.Core.Applications.Radarr
{
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);
}
catch (HttpException ex)
@@ -64,19 +63,19 @@ namespace NzbDrone.Core.Applications.Radarr
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);
}
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);
}
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());
@@ -85,7 +84,7 @@ namespace NzbDrone.Core.Applications.Radarr
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());
@@ -94,7 +93,7 @@ namespace NzbDrone.Core.Applications.Radarr
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());

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using FluentValidation.Results;
using Newtonsoft.Json;
using NLog;
@@ -34,13 +33,13 @@ namespace NzbDrone.Core.Applications.Readarr
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);
}
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);
}
@@ -48,7 +47,7 @@ namespace NzbDrone.Core.Applications.Readarr
{
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);
}
catch (HttpException ex)
@@ -64,19 +63,19 @@ namespace NzbDrone.Core.Applications.Readarr
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);
}
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);
}
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());
@@ -85,7 +84,7 @@ namespace NzbDrone.Core.Applications.Readarr
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());
@@ -94,7 +93,7 @@ namespace NzbDrone.Core.Applications.Readarr
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());

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using FluentValidation.Results;
using Newtonsoft.Json;
using NLog;
@@ -34,13 +33,13 @@ namespace NzbDrone.Core.Applications.Sonarr
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);
}
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);
}
@@ -48,7 +47,7 @@ namespace NzbDrone.Core.Applications.Sonarr
{
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);
}
catch (HttpException ex)
@@ -64,19 +63,19 @@ namespace NzbDrone.Core.Applications.Sonarr
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);
}
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);
}
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());
@@ -85,7 +84,7 @@ namespace NzbDrone.Core.Applications.Sonarr
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());
@@ -94,7 +93,7 @@ namespace NzbDrone.Core.Applications.Sonarr
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());

View File

@@ -197,7 +197,7 @@ namespace NzbDrone.Core.Configuration
public string PostgresPassword => GetValue("PostgresPassword", string.Empty, persist: false);
public string PostgresMainDb => GetValue("PostgresMainDb", "prowlarr-main", persist: false);
public string PostgresLogDb => GetValue("PostgresLogDb", "prowlarr-log", persist: false);
public int PostgresPort => GetValueInt("PostgresPort", 5432, persist: false);
public int PostgresPort => GetValueInt("PostgresPort", 5436, persist: false);
public bool LogSql => GetValueBoolean("LogSql", false, persist: false);
public int LogRotate => GetValueInt("LogRotate", 50, persist: false);
public bool FilterSentryEvents => GetValueBoolean("FilterSentryEvents", true, persist: false);

View File

@@ -1,18 +0,0 @@
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();
}
}
}

View File

@@ -11,7 +11,6 @@ using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Download;
using NzbDrone.Core.IndexerProxies;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.IndexerVersions;
using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Languages;
@@ -95,7 +94,6 @@ namespace NzbDrone.Core.Datastore
Mapper.Entity<UpdateHistory>("UpdateHistory").RegisterModel();
Mapper.Entity<AppSyncProfile>("AppSyncProfiles").RegisterModel();
Mapper.Entity<IndexerDefinitionVersion>("IndexerDefinitionVersions").RegisterModel();
}
private static void RegisterMappers()

View File

@@ -1,7 +1,6 @@
using System;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Http;
@@ -143,19 +142,15 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
return authResponse.Data.SId;
}
protected HttpRequestBuilder BuildRequest(DownloadStationSettings settings, string methodName, int apiVersion, HttpMethod httpVerb = null)
protected HttpRequestBuilder BuildRequest(DownloadStationSettings settings, string methodName, int apiVersion, HttpMethod httpVerb = HttpMethod.GET)
{
httpVerb ??= HttpMethod.Get;
var info = GetApiInfo(_apiType, settings);
return BuildRequest(settings, info, methodName, apiVersion, httpVerb);
}
private HttpRequestBuilder BuildRequest(DownloadStationSettings settings, DiskStationApiInfo apiInfo, string methodName, int apiVersion, HttpMethod httpVerb = null)
private HttpRequestBuilder BuildRequest(DownloadStationSettings settings, DiskStationApiInfo apiInfo, string methodName, int apiVersion, HttpMethod httpVerb = HttpMethod.GET)
{
httpVerb ??= HttpMethod.Get;
var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port).Resource($"webapi/{apiInfo.Path}");
requestBuilder.Method = httpVerb;
requestBuilder.LogResponseContent = true;
@@ -168,7 +163,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
throw new ArgumentOutOfRangeException(nameof(apiVersion));
}
if (httpVerb == HttpMethod.Post)
if (httpVerb == HttpMethod.POST)
{
if (apiInfo.NeedsAuthentication)
{

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Collections.Generic;
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Extensions;
@@ -25,7 +24,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
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())
{

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Http;
@@ -108,7 +107,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
{
var verifyRequest = BuildRequest(settings).Resource("/auth/verify").Build();
verifyRequest.Method = HttpMethod.Get;
verifyRequest.Method = HttpMethod.GET;
HandleRequest(verifyRequest, settings);
}
@@ -181,7 +180,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
{
var getTorrentsRequest = BuildRequest(settings).Resource("/torrents").Build();
getTorrentsRequest.Method = HttpMethod.Get;
getTorrentsRequest.Method = HttpMethod.GET;
return Json.Deserialize<TorrentListSummary>(HandleRequest(getTorrentsRequest, settings).Content).Torrents;
}
@@ -190,7 +189,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
{
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);
}
@@ -199,7 +198,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
{
var tagsRequest = BuildRequest(settings).Resource("/torrents/tags").Build();
tagsRequest.Method = HttpMethod.Patch;
tagsRequest.Method = HttpMethod.PATCH;
var body = new Dictionary<string, object>
{

View File

@@ -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")]
public int Priority { get; set; }
[FieldDefinition(9, Label = "Add Stopped", Type = FieldType.Checkbox, HelpText = "Enabling will add torrents and magnets to ruTorrent in a stopped state")]
[FieldDefinition(9, Label = "Add Stopped", Type = FieldType.Checkbox, HelpText = "Enabling will prevent magnets from downloading before downloading")]
public bool AddStopped { get; set; }
public NzbDroneValidationResult Validate()

View File

@@ -1,48 +0,0 @@
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;
}
}

View File

@@ -35,13 +35,10 @@ namespace NzbDrone.Core.HealthCheck.Checks
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(),
healthType,
healthMessage,
HealthCheckResult.Warning,
string.Format(_localizationService.GetLocalizedString("IndexerObsoleteCheckMessage"),
string.Join(", ", oldIndexers.Select(v => v.Definition.Name))),
"#indexers-are-obsolete");
}

View File

@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using FluentValidation.Results;
using Newtonsoft.Json;
using NLog;
@@ -116,7 +115,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 maxTimeout = Settings.RequestTimeout * 1000;
if (request.Method == HttpMethod.Get)
if (request.Method == HttpMethod.GET)
{
req = new FlareSolverrRequestGet
{
@@ -126,7 +125,7 @@ namespace NzbDrone.Core.IndexerProxies.FlareSolverr
UserAgent = userAgent
};
}
else if (request.Method == HttpMethod.Post)
else if (request.Method == HttpMethod.POST)
{
var contentTypeType = request.Headers.ContentType;
@@ -168,7 +167,7 @@ namespace NzbDrone.Core.IndexerProxies.FlareSolverr
var newRequest = new HttpRequest(apiUrl, HttpAccept.Json);
newRequest.Headers.ContentType = "application/json";
newRequest.Method = HttpMethod.Post;
newRequest.Method = HttpMethod.POST;
newRequest.SetContent(req.ToJson());
_logger.Debug("Applying FlareSolverr Proxy {0} to request {1}", Name, request.Url);

View File

@@ -142,7 +142,7 @@ namespace NzbDrone.Core.IndexerSearch
private async Task<List<ReleaseInfo>> Dispatch(Func<IIndexer, Task<IndexerPageableQueryResult>> searchAction, SearchCriteriaBase criteriaBase)
{
var indexers = _indexerFactory.Enabled();
var indexers = _indexerFactory.GetAvailableProviders();
if (criteriaBase.IndexerIds != null && criteriaBase.IndexerIds.Count > 0)
{

View File

@@ -6,11 +6,10 @@ using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers.Cardigann;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
@@ -19,18 +18,15 @@ namespace NzbDrone.Core.IndexerVersions
public interface IIndexerDefinitionUpdateService
{
List<CardigannMetaDefinition> All();
CardigannDefinition GetCachedDefinition(string fileKey);
CardigannDefinition GetDefinition(string fileKey);
List<string> GetBlocklist();
}
public class IndexerDefinitionUpdateService : IIndexerDefinitionUpdateService, IExecute<IndexerDefinitionUpdateCommand>, IHandle<ApplicationStartedEvent>
public class IndexerDefinitionUpdateService : IIndexerDefinitionUpdateService, IExecute<IndexerDefinitionUpdateCommand>
{
/* 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;
//Used when moving yml to C#
private readonly List<string> _defintionBlocklist = new List<string>()
{
"aither",
@@ -53,7 +49,6 @@ namespace NzbDrone.Core.IndexerVersions
private readonly IHttpClient _httpClient;
private readonly IAppFolderInfo _appFolderInfo;
private readonly IDiskProvider _diskProvider;
private readonly IIndexerDefinitionVersionService _versionService;
private readonly ICached<CardigannDefinition> _cache;
private readonly Logger _logger;
@@ -65,13 +60,11 @@ namespace NzbDrone.Core.IndexerVersions
public IndexerDefinitionUpdateService(IHttpClient httpClient,
IAppFolderInfo appFolderInfo,
IDiskProvider diskProvider,
IIndexerDefinitionVersionService versionService,
ICacheManager cacheManager,
Logger logger)
{
_appFolderInfo = appFolderInfo;
_diskProvider = diskProvider;
_versionService = versionService;
_cache = cacheManager.GetCache<CardigannDefinition>(typeof(CardigannDefinition), "definitions");
_httpClient = httpClient;
_logger = logger;
@@ -83,24 +76,43 @@ namespace NzbDrone.Core.IndexerVersions
try
{
// Grab latest def list from server or fallback to disk
try
var request = new HttpRequest($"https://indexers.prowlarr.com/master/{DEFINITION_VERSION}");
var response = _httpClient.Get<List<CardigannMetaDefinition>>(request);
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 request = new HttpRequest($"https://indexers.prowlarr.com/{DEFINITION_BRANCH}/{DEFINITION_VERSION}");
var response = _httpClient.Get<List<CardigannMetaDefinition>>(request);
indexerList = response.Resource.Where(i => !_defintionBlocklist.Contains(i.File)).ToList();
var files = directoryInfo.GetFiles($"*.yml");
foreach (var file in files)
{
_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
{
@@ -110,14 +122,14 @@ namespace NzbDrone.Core.IndexerVersions
return indexerList;
}
public CardigannDefinition GetCachedDefinition(string fileKey)
public CardigannDefinition GetDefinition(string file)
{
if (string.IsNullOrEmpty(fileKey))
if (string.IsNullOrEmpty(file))
{
throw new ArgumentNullException(nameof(fileKey));
throw new ArgumentNullException(nameof(file));
}
var definition = _cache.Get(fileKey, () => GetUncachedDefinition(fileKey));
var definition = _cache.Get(file, () => LoadIndexerDef(file));
return definition;
}
@@ -127,46 +139,15 @@ namespace NzbDrone.Core.IndexerVersions
return _defintionBlocklist;
}
private List<CardigannMetaDefinition> ReadDefinitionsFromDisk(List<CardigannMetaDefinition> defs, string path, SearchOption options = SearchOption.TopDirectoryOnly)
private CardigannDefinition GetHttpDefinition(string id)
{
var indexerList = defs;
var directoryInfo = new DirectoryInfo(path);
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;
var req = new HttpRequest($"https://indexers.prowlarr.com/master/{DEFINITION_VERSION}/{id}");
var response = _httpClient.Get(req);
var definition = _deserializer.Deserialize<CardigannDefinition>(response.Content);
return CleanIndexerDefinition(definition);
}
private CardigannDefinition GetUncachedDefinition(string fileKey)
private CardigannDefinition LoadIndexerDef(string fileKey)
{
if (string.IsNullOrEmpty(fileKey))
{
@@ -201,26 +182,9 @@ 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);
}
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)
{
if (definition.Settings == null)
@@ -260,12 +224,6 @@ namespace NzbDrone.Core.IndexerVersions
return definition;
}
public void Handle(ApplicationStartedEvent message)
{
// Sync indexers on app start
UpdateLocalDefinitions();
}
public void Execute(IndexerDefinitionUpdateCommand message)
{
UpdateLocalDefinitions();
@@ -280,46 +238,29 @@ namespace NzbDrone.Core.IndexerVersions
private void UpdateLocalDefinitions()
{
var startupFolder = _appFolderInfo.AppDataFolder;
var request = new HttpRequest($"https://indexers.prowlarr.com/{DEFINITION_BRANCH}/{DEFINITION_VERSION}");
var request = new HttpRequest($"https://indexers.prowlarr.com/master/{DEFINITION_VERSION}");
var response = _httpClient.Get<List<CardigannMetaDefinition>>(request);
var currentDefs = _versionService.All().ToDictionary(x => x.DefinitionId, x => x.Sha);
try
foreach (var def in response.Resource)
{
EnsureDefinitionsFolder();
foreach (var def in response.Resource)
try
{
try
{
var saveFile = Path.Combine(startupFolder, "Definitions", $"{def.File}.yml");
var startupFolder = _appFolderInfo.AppDataFolder;
if (currentDefs.TryGetValue(def.Id, out var defSha) && defSha == def.Sha)
{
_logger.Trace("Indexer already up to date: {0}", def.File);
EnsureDefinitionsFolder();
continue;
}
var saveFile = Path.Combine(startupFolder, "Definitions", $"{def.File}.yml");
_httpClient.DownloadFile($"https://indexers.prowlarr.com/{DEFINITION_BRANCH}/{DEFINITION_VERSION}/{def.File}", saveFile);
_httpClient.DownloadFile($"https://indexers.prowlarr.com/master/{DEFINITION_VERSION}/{def.File}", saveFile);
_versionService.Upsert(new IndexerDefinitionVersion { Sha = def.Sha, DefinitionId = def.Id, File = def.File, LastUpdated = DateTime.UtcNow });
_cache.Remove(def.File);
_cache.Remove(def.File);
_logger.Debug("Updated definition: {0}", def.File);
}
catch (Exception ex)
{
_logger.Error("Definition download failed: {0}, {1}", def.File, ex.Message);
}
_logger.Debug("Updated definition: {0}", def.File);
}
catch (Exception ex)
{
_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);
}
}
}

View File

@@ -1,13 +0,0 @@
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; }
}
}

View File

@@ -1,25 +0,0 @@
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();
}
}
}

View File

@@ -1,66 +0,0 @@
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);
}
}
}

View File

@@ -60,7 +60,7 @@ namespace NzbDrone.Core.Indexers.Definitions
var mainPage = await ExecuteAuth(new HttpRequest(Settings.BaseUrl));
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = Common.Http.HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
requestBuilder.SetCookies(mainPage.GetCookies());
@@ -167,7 +167,7 @@ namespace NzbDrone.Core.Indexers.Definitions
if (isSearch)
{
request.HttpRequest.Method = HttpMethod.Post;
request.HttpRequest.Method = NzbDrone.Common.Http.HttpMethod.POST;
var postData = new NameValueCollection
{
{ "do", "search" },

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AngleSharp.Html.Parser;
@@ -58,7 +57,7 @@ namespace NzbDrone.Core.Indexers.Definitions
};
var loginPage = await ExecuteAuth(new HttpRequest(LoginUrl));
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
requestBuilder.SetCookies(loginPage.GetCookies());

View File

@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using AngleSharp.Html.Parser;
@@ -57,7 +56,7 @@ namespace NzbDrone.Core.Indexers.Definitions
AllowAutoRedirect = true
};
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var cookies = Cookies;

View File

@@ -1,6 +1,5 @@
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using FluentValidation.Results;
using NLog;
@@ -106,7 +105,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
LogResponseContent = true
};
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var authLoginRequest = requestBuilder

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -56,7 +55,7 @@ namespace NzbDrone.Core.Indexers.Definitions
AllowAutoRedirect = true
};
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var cookies = Cookies;

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AngleSharp.Dom;
@@ -80,7 +79,7 @@ namespace NzbDrone.Core.Indexers.Definitions
var loginPage = await ExecuteAuth(new HttpRequest(LoginUrl));
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
requestBuilder.SetCookies(loginPage.GetCookies());

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using FluentValidation;
using Newtonsoft.Json;
using NLog;
@@ -111,7 +110,7 @@ namespace NzbDrone.Core.Indexers.Definitions
var request = new HttpRequest(searchUrl, HttpAccept.Json);
request.Headers.Add("Content-type", "application/json");
request.Method = HttpMethod.Post;
request.Method = HttpMethod.POST;
request.SetContent(body.ToJson());
var indexerRequest = new IndexerRequest(request);

View File

@@ -37,7 +37,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
{
var generator = _generatorCache.Get(Settings.DefinitionFile, () =>
new CardigannRequestGenerator(_configService,
_definitionService.GetCachedDefinition(Settings.DefinitionFile),
_definitionService.GetDefinition(Settings.DefinitionFile),
_logger)
{
HttpClient = _httpClient,
@@ -57,7 +57,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
public override IParseIndexerResponse GetParser()
{
return new CardigannParser(_configService,
_definitionService.GetCachedDefinition(Settings.DefinitionFile),
_definitionService.GetDefinition(Settings.DefinitionFile),
_logger)
{
Settings = Settings

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using AngleSharp.Html.Dom;
@@ -185,7 +184,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
var requestBuilder = new HttpRequestBuilder(loginUrl)
{
LogResponseContent = true,
Method = HttpMethod.Post,
Method = HttpMethod.POST,
AllowAutoRedirect = true,
SuppressHttpError = true,
Encoding = _encoding
@@ -330,7 +329,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
var requestBuilder = new HttpRequestBuilder(captchaUrl.ToString())
{
LogResponseContent = true,
Method = HttpMethod.Get,
Method = HttpMethod.GET,
Encoding = _encoding
};
@@ -395,7 +394,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
var requestBuilder = new HttpRequestBuilder(submitUrl.ToString())
{
LogResponseContent = true,
Method = HttpMethod.Post,
Method = HttpMethod.POST,
AllowAutoRedirect = true,
Encoding = _encoding
};
@@ -424,7 +423,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
var requestBuilder = new HttpRequestBuilder(submitUrl.ToString())
{
LogResponseContent = true,
Method = HttpMethod.Post,
Method = HttpMethod.POST,
AllowAutoRedirect = true,
SuppressHttpError = true,
Encoding = _encoding
@@ -467,7 +466,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
var requestBuilder = new HttpRequestBuilder(loginUrl)
{
LogResponseContent = true,
Method = HttpMethod.Get,
Method = HttpMethod.GET,
SuppressHttpError = true,
Encoding = _encoding
};
@@ -492,7 +491,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
var requestBuilder = new HttpRequestBuilder(loginUrl)
{
LogResponseContent = true,
Method = HttpMethod.Get,
Method = HttpMethod.GET,
SuppressHttpError = true,
Encoding = _encoding
};
@@ -566,7 +565,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
var requestBuilder = new HttpRequestBuilder(loginUrl.AbsoluteUri)
{
LogResponseContent = true,
Method = HttpMethod.Get,
Method = HttpMethod.GET,
Encoding = _encoding
};
@@ -667,21 +666,21 @@ namespace NzbDrone.Core.Indexers.Cardigann
Dictionary<string, string> pairs = null;
var queryCollection = new NameValueCollection();
var method = HttpMethod.Get;
var method = HttpMethod.GET;
if (string.Equals(request.Method, "post", StringComparison.OrdinalIgnoreCase))
{
method = HttpMethod.Post;
method = HttpMethod.POST;
pairs = new Dictionary<string, string>();
}
foreach (var input in request.Inputs)
{
var value = ApplyGoTemplateText(input.Value, variables);
if (method == HttpMethod.Get)
if (method == HttpMethod.GET)
{
queryCollection.Add(input.Key, value);
}
else if (method == HttpMethod.Post)
else if (method == HttpMethod.POST)
{
pairs.Add(input.Key, value);
}
@@ -708,7 +707,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
httpRequest.Method = method;
// Add form data for POST requests
if (method == HttpMethod.Post)
if (method == HttpMethod.POST)
{
foreach (var param in pairs)
{
@@ -725,7 +724,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
public async Task<HttpRequest> DownloadRequest(Uri link)
{
Cookies = GetCookies();
var method = HttpMethod.Get;
var method = HttpMethod.GET;
var headers = new Dictionary<string, string>();
var variables = GetBaseTemplateVariables();
@@ -760,7 +759,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
if (download.Method == "post")
{
method = HttpMethod.Post;
method = HttpMethod.POST;
}
if (download.Infohash != null)
@@ -1015,11 +1014,11 @@ namespace NzbDrone.Core.Indexers.Cardigann
// 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 queryCollection = new List<KeyValuePair<string, string>>();
var method = HttpMethod.Get;
var method = HttpMethod.GET;
if (string.Equals(searchPath.Method, "post", StringComparison.OrdinalIgnoreCase))
{
method = HttpMethod.Post;
method = HttpMethod.POST;
}
var inputsList = new List<Dictionary<string, string>>();
@@ -1065,7 +1064,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
}
}
if (method == HttpMethod.Get)
if (method == HttpMethod.GET)
{
if (queryCollection.Count > 0)
{
@@ -1080,7 +1079,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
requestbuilder.Method = method;
// Add FormData for searchs that POST
if (method == HttpMethod.Post)
if (method == HttpMethod.POST)
{
foreach (var param in queryCollection)
{

View File

@@ -22,7 +22,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class DanishBytes : TorrentIndexerBase<DanishBytesSettings>
{
public override string Name => "DanishBytes";
public override string[] IndexerUrls => new string[] { "https://danishbytes.club/", "https://danishbytes2.org/" };
public override string[] IndexerUrls => new string[] { "https://danishbytes.club/" };
public override string Description => "DanishBytes is a Private Danish Tracker";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;

View File

@@ -1,5 +1,4 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using NLog;
using NzbDrone.Common.Http;
@@ -57,7 +56,7 @@ namespace NzbDrone.Core.Indexers.Gazelle
LogResponseContent = true
};
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var cookies = Cookies;

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
@@ -51,7 +50,7 @@ namespace NzbDrone.Core.Indexers.HDBits
.Resource("/api/torrents")
.Build();
request.Method = HttpMethod.Post;
request.Method = HttpMethod.POST;
const string appJson = "application/json";
request.Headers.Accept = appJson;
request.Headers.ContentType = appJson;

View File

@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -58,7 +57,7 @@ namespace NzbDrone.Core.Indexers.Definitions
AllowAutoRedirect = true
};
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var cookies = Cookies;

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AngleSharp.Html.Parser;
@@ -53,7 +52,7 @@ namespace NzbDrone.Core.Indexers.Definitions
LogResponseContent = true
};
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var cookies = Cookies;

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using AngleSharp.Html.Parser;
using FluentValidation;
@@ -55,7 +54,7 @@ namespace NzbDrone.Core.Indexers.Definitions
LogResponseContent = true
};
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var cookies = Cookies;

View File

@@ -1,341 +0,0 @@
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));
}
}

View File

@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -54,7 +53,7 @@ namespace NzbDrone.Core.Indexers.Definitions
LogResponseContent = true
};
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var cookies = Cookies;

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Xml;
using System.Xml.Linq;
using NLog;
@@ -51,7 +50,7 @@ namespace NzbDrone.Core.Indexers.Newznab
var request = new HttpRequest(url, HttpAccept.Rss);
request.AllowAutoRedirect = true;
request.Method = HttpMethod.Get;
request.Method = HttpMethod.GET;
HttpResponse response;

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -80,7 +79,7 @@ namespace NzbDrone.Core.Indexers.Definitions
{
LogResponseContent = true,
AllowAutoRedirect = true,
Method = HttpMethod.Post
Method = HttpMethod.POST
};
var authLoginCheckRequest = requestBuilder3

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -29,7 +28,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public override string Language => "ru-ru";
public override Encoding Encoding => Encoding.GetEncoding("windows-1251");
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.SemiPrivate;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities();
public PornoLab(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
@@ -53,7 +52,7 @@ namespace NzbDrone.Core.Indexers.Definitions
{
LogResponseContent = true,
AllowAutoRedirect = true,
Method = HttpMethod.Post
Method = HttpMethod.POST
};
var authLoginRequest = requestBuilder

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -60,7 +59,7 @@ namespace NzbDrone.Core.Indexers.Definitions
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.SetCookies(loginPage.GetCookies());

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using AngleSharp.Html.Parser;
using FluentValidation;
@@ -59,7 +58,7 @@ namespace NzbDrone.Core.Indexers.Definitions
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.SetCookies(loginPage.GetCookies());

View File

@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -32,7 +31,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public override string Language => "ru-org";
public override Encoding Encoding => Encoding.GetEncoding("windows-1251");
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.SemiPrivate;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities();
public RuTracker(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
@@ -58,7 +57,7 @@ namespace NzbDrone.Core.Indexers.Definitions
AllowAutoRedirect = true
};
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var cookies = Cookies;

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Mime;
using System.Text;
using System.Threading.Tasks;
@@ -76,7 +75,7 @@ namespace NzbDrone.Core.Indexers.Definitions
{
LogResponseContent = true,
AllowAutoRedirect = true,
Method = HttpMethod.Post,
Method = HttpMethod.POST,
};
var request = requestBuilder.Build();

View File

@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -58,7 +57,7 @@ namespace NzbDrone.Core.Indexers.Definitions
{
var requestBuilder = new HttpRequestBuilder(string.Format("{0}/{1}", Settings.BaseUrl.TrimEnd('/'), "checkpoint/API"))
{
Method = HttpMethod.Post,
Method = HttpMethod.POST,
LogResponseContent = true,
AllowAutoRedirect = true
};
@@ -78,7 +77,7 @@ namespace NzbDrone.Core.Indexers.Definitions
var requestBuilder2 = new HttpRequestBuilder(string.Format("{0}/{1}", Settings.BaseUrl.TrimEnd('/'), "checkpoint/"))
{
Method = HttpMethod.Post,
Method = HttpMethod.POST,
LogResponseContent = true,
AllowAutoRedirect = true
};

View File

@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -60,7 +59,7 @@ namespace NzbDrone.Core.Indexers.Definitions
AllowAutoRedirect = true
};
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
var cookies = Cookies;

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using FluentValidation;
@@ -55,7 +54,7 @@ namespace NzbDrone.Core.Indexers.Definitions
LogResponseContent = true
};
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var cookies = Cookies;

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AngleSharp.Html.Parser;
@@ -64,7 +63,7 @@ namespace NzbDrone.Core.Indexers.Definitions
var json1 = JObject.Parse(loginPage.Content);
var captchaSelection = json1["images"][0]["hash"];
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
requestBuilder.SetCookies(loginPage.GetCookies());

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
@@ -80,7 +79,7 @@ namespace NzbDrone.Core.Indexers.Definitions
LogResponseContent = true
};
requestBuilder.Method = HttpMethod.Post;
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
requestBuilder.SetCookies(loginPage.GetCookies());
@@ -103,7 +102,7 @@ namespace NzbDrone.Core.Indexers.Definitions
LogResponseContent = true
};
requestBuilder2.Method = HttpMethod.Post;
requestBuilder2.Method = HttpMethod.POST;
requestBuilder2.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
requestBuilder2.SetCookies(response.GetCookies());

View File

@@ -4,7 +4,6 @@ using System.Linq;
using System.Text;
using FluentValidation.Results;
using NLog;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Indexers.Cardigann;
using NzbDrone.Core.Indexers.Newznab;
using NzbDrone.Core.IndexerVersions;
@@ -46,27 +45,16 @@ namespace NzbDrone.Core.Indexers
public override List<IndexerDefinition> All()
{
var definitions = base.All();
var filteredDefinitions = new List<IndexerDefinition>();
foreach (var definition in definitions)
{
if (definition.Implementation == typeof(Cardigann.Cardigann).Name)
{
try
{
MapCardigannDefinition(definition);
}
catch
{
// Skip indexer if we fail in Cardigann mapping
_logger.Debug("Indexer {0} has no definition", definition.Name);
}
MapCardigannDefinition(definition);
}
filteredDefinitions.Add(definition);
}
return filteredDefinitions;
return definitions;
}
public override IndexerDefinition Get(int id)
@@ -75,14 +63,7 @@ namespace NzbDrone.Core.Indexers
if (definition.Implementation == typeof(Cardigann.Cardigann).Name)
{
try
{
MapCardigannDefinition(definition);
}
catch
{
throw new ModelNotFoundException(typeof(IndexerDefinition), id);
}
MapCardigannDefinition(definition);
}
return definition;
@@ -96,7 +77,7 @@ namespace NzbDrone.Core.Indexers
private void MapCardigannDefinition(IndexerDefinition definition)
{
var settings = (CardigannSettings)definition.Settings;
var defFile = _definitionService.GetCachedDefinition(settings.DefinitionFile);
var defFile = _definitionService.GetDefinition(settings.DefinitionFile);
definition.ExtraFields = defFile.Settings;
if (defFile.Login?.Captcha != null && !definition.ExtraFields.Any(x => x.Type == "cardigannCaptcha"))

View File

@@ -28,17 +28,17 @@ namespace NzbDrone.Core.Indexers
{
if (indexer.Id > 0 && ((IIndexerSettings)indexer.Settings).BaseSettings.GrabLimit.HasValue)
{
var grabCount = _historyService.CountSince(indexer.Id, DateTime.Now.AddHours(-24), new List<HistoryEventType> { HistoryEventType.ReleaseGrabbed });
var grabLimit = ((IIndexerSettings)indexer.Settings).BaseSettings.GrabLimit;
var grabCount = _historyService.CountSince(indexer.Id, DateTime.Now.StartOfDay(), new List<HistoryEventType> { HistoryEventType.ReleaseGrabbed });
var grabLimit = ((IIndexerSettings)indexer.Settings).BaseSettings.QueryLimit;
if (grabCount > grabLimit)
{
_logger.Info("Indexer {0} has exceeded maximum grab limit for last 24 hours", indexer.Name);
_logger.Info("Indexer {0} has exceeded maximum grab limit for today", indexer.Name);
return true;
}
_logger.Debug("Indexer {0} has performed {1} of possible {2} grabs in last 24 hours, proceeding", indexer.Name, grabCount, grabLimit);
_logger.Debug("Indexer {0} has performed {1} of possible {2} grabs for today, proceeding", indexer.Name, grabCount, grabLimit);
}
return false;
@@ -48,17 +48,17 @@ namespace NzbDrone.Core.Indexers
{
if (indexer.Id > 0 && ((IIndexerSettings)indexer.Settings).BaseSettings.QueryLimit.HasValue)
{
var queryCount = _historyService.CountSince(indexer.Id, DateTime.Now.AddHours(-24), new List<HistoryEventType> { HistoryEventType.IndexerQuery, HistoryEventType.IndexerRss });
var queryCount = _historyService.CountSince(indexer.Id, DateTime.Now.StartOfDay(), new List<HistoryEventType> { HistoryEventType.IndexerQuery, HistoryEventType.IndexerRss });
var queryLimit = ((IIndexerSettings)indexer.Settings).BaseSettings.QueryLimit;
if (queryCount > queryLimit)
{
_logger.Info("Indexer {0} has exceeded maximum query limit for last 24 hours", indexer.Name);
_logger.Info("Indexer {0} has exceeded maximum query limit for today", indexer.Name);
return true;
}
_logger.Debug("Indexer {0} has performed {1} of possible {2} queries in last 24 hours, proceeding", indexer.Name, queryCount, queryLimit);
_logger.Debug("Indexer {0} has performed {1} of possible {2} queries for today, proceeding", indexer.Name, queryCount, queryLimit);
}
return false;

View File

@@ -128,8 +128,10 @@ namespace NzbDrone.Core.Instrumentation
private void WriteSqliteLog(Log log, string connectionString)
{
using (var connection =
new SQLiteConnection(connectionString).OpenAndReturn())
SQLiteFactory.Instance.CreateConnection())
{
connection.ConnectionString = connectionString;
connection.Open();
using (var sqlCommand = connection.CreateCommand())
{
sqlCommand.CommandText = INSERT_COMMAND;

View File

@@ -85,7 +85,6 @@
"CouldNotConnectSignalR": "Could not connect to SignalR, UI won't update",
"Custom": "Custom",
"CustomFilters": "Custom Filters",
"Database": "Database",
"Date": "Date",
"Dates": "Dates",
"DBMigration": "DB Migration",
@@ -170,7 +169,6 @@
"IllRestartLater": "I'll restart later",
"IncludeHealthWarningsHelpText": "Include Health Warnings",
"Indexer": "Indexer",
"IndexerAlreadySetup": "At least one instace of indexer is already setup",
"IndexerAuth": "Indexer Auth",
"IndexerFlags": "Indexer Flags",
"IndexerHealthCheckNoIndexers": "No indexers enabled, Prowlarr will not return search results",
@@ -178,7 +176,6 @@
"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}",
"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",
"IndexerPriorityHelpText": "Indexer Priority from 1 (Highest) to 50 (Lowest). Default: 25.",
"IndexerProxies": "Indexer Proxies",

View File

@@ -1,4 +1,3 @@
using System.Net.Http;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
@@ -30,7 +29,7 @@ namespace NzbDrone.Core.Notifications.Discord
.Accept(HttpAccept.Json)
.Build();
request.Method = HttpMethod.Post;
request.Method = HttpMethod.POST;
request.Headers.ContentType = "application/json";
request.SetContent(payload.ToJson());

View File

@@ -1,5 +1,4 @@
using System;
using System.Net.Http;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common.Extensions;
@@ -28,7 +27,7 @@ namespace NzbDrone.Core.Notifications.Join
public void SendNotification(string title, string message, JoinSettings settings)
{
var method = HttpMethod.Get;
var method = HttpMethod.GET;
try
{

View File

@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common.Extensions;
@@ -101,7 +100,7 @@ namespace NzbDrone.Core.Notifications.PushBullet
var request = requestBuilder.Build();
request.Method = HttpMethod.Get;
request.Method = HttpMethod.GET;
request.AddBasicAuthentication(settings.ApiKey, string.Empty);
var response = _httpClient.Execute(request);

View File

@@ -1,5 +1,4 @@
using System.Net;
using System.Net.Http;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
@@ -23,7 +22,7 @@ namespace NzbDrone.Core.Notifications.SendGrid
{
try
{
var request = BuildRequest(settings, "mail/send", HttpMethod.Post);
var request = BuildRequest(settings, "mail/send", HttpMethod.POST);
var payload = new SendGridPayload
{

View File

@@ -1,4 +1,3 @@
using System.Net.Http;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
@@ -30,7 +29,7 @@ namespace NzbDrone.Core.Notifications.Slack
.Accept(HttpAccept.Json)
.Build();
request.Method = HttpMethod.Post;
request.Method = HttpMethod.POST;
request.Headers.ContentType = "application/json";
request.SetContent(payload.ToJson());

View File

@@ -1,11 +1,10 @@
using System.Net.Http;
using NzbDrone.Common.Http;
namespace NzbDrone.Core.Notifications.Webhook
{
public enum WebhookMethod
{
POST = 1,
PUT = 2
POST = HttpMethod.POST,
PUT = HttpMethod.PUT
}
}

View File

@@ -1,5 +1,3 @@
using System;
using System.Net.Http;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
@@ -28,13 +26,7 @@ namespace NzbDrone.Core.Notifications.Webhook
.Accept(HttpAccept.Json)
.Build();
request.Method = settings.Method switch
{
(int)WebhookMethod.POST => HttpMethod.Post,
(int)WebhookMethod.PUT => HttpMethod.Put,
_ => throw new ArgumentOutOfRangeException($"Invalid Webhook method {settings.Method}")
};
request.Method = (HttpMethod)settings.Method;
request.Headers.ContentType = "application/json";
request.SetContent(body.ToJson());

View File

@@ -16,26 +16,14 @@ namespace NzbDrone.Core.Parser
public static string NormalizeMultiSpaces(string s) =>
new Regex(@"\s+").Replace(s.Trim(), " ");
private static string NormalizeNumber(string s, bool isInt = false)
private static string NormalizeNumber(string s)
{
var valStr = new string(s.Where(c => char.IsDigit(c) || c == '.' || c == ',').ToArray());
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(",", ".");
valStr = valStr.Trim().Replace("-", "0");
if (valStr.Count(c => c == '.') > 1)
{
var lastOcc = valStr.LastIndexOf('.');
@@ -51,17 +39,17 @@ namespace NzbDrone.Core.Parser
public static float CoerceFloat(string str) => float.Parse(NormalizeNumber(str), NumberStyles.Any, CultureInfo.InvariantCulture);
public static int CoerceInt(string str) => int.Parse(NormalizeNumber(str, true), NumberStyles.Any, CultureInfo.InvariantCulture);
public static int CoerceInt(string str) => int.Parse(NormalizeNumber(str), NumberStyles.Any, CultureInfo.InvariantCulture);
public static long CoerceLong(string str) => long.Parse(NormalizeNumber(str, true), NumberStyles.Any, CultureInfo.InvariantCulture);
public static long CoerceLong(string str) => long.Parse(NormalizeNumber(str), 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 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, true), 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 TryCoerceLong(string str, out long result) => long.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 long? GetLongFromString(string str)
{

View File

@@ -1,4 +1,3 @@
using System.Data.SQLite;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
@@ -7,7 +6,6 @@ using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Processes;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.Messaging;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Host
@@ -101,7 +99,6 @@ namespace NzbDrone.Host
return args;
}
[EventHandleOrder(EventHandleOrder.Last)]
public void Handle(ApplicationShutdownRequested message)
{
if (!_runtimeInfo.IsWindowsService)

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Diagnostics;
using System.IO;
using System.Reflection;
@@ -100,11 +99,6 @@ namespace NzbDrone.Host
Logger.Info(e.Message);
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)

View File

@@ -15,7 +15,6 @@ namespace Prowlarr.Api.V1.Indexers
public class IndexerResource : ProviderResource<IndexerResource>
{
public string[] IndexerUrls { get; set; }
public string DefinitionName { get; set; }
public string Description { get; set; }
public string Language { get; set; }
public string Encoding { get; set; }
@@ -52,8 +51,6 @@ namespace Prowlarr.Api.V1.Indexers
var resource = base.ToResource(definition);
resource.DefinitionName = definition.ImplementationName;
var infoLinkName = definition.ImplementationName;
if (definition.Implementation == typeof(Cardigann).Name)
@@ -74,7 +71,6 @@ namespace Prowlarr.Api.V1.Indexers
}
}
resource.DefinitionName = settings.DefinitionFile;
infoLinkName = settings.DefinitionFile;
}
@@ -114,7 +110,7 @@ namespace Prowlarr.Api.V1.Indexers
var settings = (CardigannSettings)definition.Settings;
var cardigannDefinition = _definitionService.GetCachedDefinition(settings.DefinitionFile);
var cardigannDefinition = _definitionService.GetDefinition(settings.DefinitionFile);
foreach (var field in resource.Fields)
{

View File

@@ -148,11 +148,11 @@ namespace NzbDrone.Api.V1.Indexers
foreach (var result in results.Releases)
{
result.DownloadUrl = result.DownloadUrl.IsNotNullOrWhiteSpace() ? _downloadMappingService.ConvertToProxyLink(new Uri(result.DownloadUrl), request.server, indexerDef.Id, result.Title).AbsoluteUri : null;
result.DownloadUrl = result.DownloadUrl.IsNotNullOrWhiteSpace() ? _downloadMappingService.ConvertToProxyLink(new Uri(result.DownloadUrl), request.server, indexerDef.Id, result.Title).ToString() : null;
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).AbsoluteUri : null;
((TorrentInfo)result).MagnetUrl = ((TorrentInfo)result).MagnetUrl.IsNotNullOrWhiteSpace() ? _downloadMappingService.ConvertToProxyLink(new Uri(((TorrentInfo)result).MagnetUrl), request.server, indexerDef.Id, result.Title).ToString() : null;
}
}

Some files were not shown because too many files have changed in this diff Show More