Compare commits

...

46 Commits

Author SHA1 Message Date
Qstick
3ca6f83a4d fixup! New: (Cardigann) Paging Support 2023-02-26 17:06:47 -06:00
Qstick
fb5b325271 fixup! New: (Cardigann) Add AllowEmptyInputs
Co-Authored-By: Bogdan <mynameisbogdan@users.noreply.github.com>
2023-02-26 16:48:53 -06:00
Qstick
ec8025c3dc New: (Cardigann) Add AllowEmptyInputs
Co-Authored-By: Bogdan <mynameisbogdan@users.noreply.github.com>
2023-02-26 16:41:02 -06:00
Qstick
b42bf2cf20 New: (Cardigann) Paging Support 2023-02-25 20:18:21 -06:00
Qstick
712d95e6ce Cleanup request paging code 2023-02-25 20:17:46 -06:00
Bogdan
24f6c937da Fixed: (Cardigann) Prevent fetching the first page multiple times 2023-02-26 01:56:56 +02:00
Bogdan
e94aa7c499 Fixed: (DateTimeUtil) Move check for Rfc1123ZPattern
Co-authored-by: Sergey M <msergein@users.noreply.github.com>
2023-02-25 23:55:42 +02:00
Bogdan
201bc1944b Fixed: (DateTimeUtil) Check first for Standard Format in ParseDateTimeGoLang 2023-02-25 23:16:57 +02:00
Bogdan
09e40e0060 Fixed: (Rarbg) Set rate limit to 31s for RSS sync 2023-02-25 19:56:06 +02:00
Qstick
348d90a37e Fixed: (Cardigann) Invariant date string parsing for "reltime", "timeago", "fuzzytime"
Fixes #835
2023-02-25 11:52:24 -06:00
Qstick
726dc34424 Improve GetLongFromString and ParseFields
2700X faster
2023-02-25 11:52:24 -06:00
Qstick
2e9f6cd94b More Improvement to unix timestamp performance 2023-02-25 11:52:24 -06:00
Bogdan
495f61f412 Improve unix timestamp performance 2023-02-25 11:52:24 -06:00
Qstick
0f11f414b6 Benchmark Framework 2023-02-25 11:52:24 -06:00
Bogdan
d397cdf5fb Fixed: (Cardigann) Implement validate as field filter 2023-02-25 17:45:34 +02:00
Bogdan
888b514dd8 Fixed: (Cardigann) Switch to DateTime standard 2023-02-24 15:26:44 +02:00
Bogdan
caab337379 Fixed: (Cardigann) Parse text templates only if necessary 2023-02-23 08:02:37 +02:00
Bogdan
26bea14137 Fixed: (GreatPosterWall) Use cookies for 2FA
Co-authored-by: ilike2burnthing <59480337+ilike2burnthing@users.noreply.github.com>
2023-02-23 07:01:36 +02:00
Qstick
5f26287234 Bump version to 1.3.1 2023-02-22 21:40:18 -06:00
Bogdan
6ec761c217 Fixed: (Cardigann) Change UseBeforeResponse to Usebeforeresponse 2023-02-23 02:13:41 +02:00
Bogdan
b85679de56 Fixed: Filter releases with null description 2023-02-23 01:29:56 +02:00
Bogdan
71775b97a3 Fixed: (Rarbg) Check for rate limits before parsing token errors 2023-02-22 09:30:22 +02:00
bakerboy448
5bb3dbfbf5 Fixed: (Rarbg) Change app_id per site request 2023-02-21 23:39:30 +02:00
Bogdan
b608a7a904 Fixed: (FunFile) Change download url 2023-02-21 23:32:50 +02:00
Bogdan
4ad992f76a Fixed: (UI) Replace api. only if it's a subdomain 2023-02-21 22:59:08 +02:00
Bogdan
95497480a2 Fixed: (GreatPosterWall) Remove cookies only if redirected to login.php 2023-02-21 02:42:26 +02:00
Qstick
cc57866ab0 New: Filter releases by search criteria
Co-Authored-By: Bogdan <mynameisbogdan@users.noreply.github.com>
2023-02-20 18:41:39 -06:00
Qstick
dbc4989a95 Fixed: (IndexerSearch) Update isRss logic for new properties 2023-02-20 18:41:39 -06:00
Bogdan
af4961e3e6 Fixed: (Rarbg) update cats 2023-02-21 02:38:29 +02:00
Bogdan
0ec54906c6 Fixed: (Caridgann) Custom headers in login and download blocks 2023-02-21 02:37:49 +02:00
Qstick
35f85fc986 More update tests 2023-02-19 23:40:53 -06:00
Qstick
0aedafb278 Fix update tests 2023-02-19 23:09:35 -06:00
Qstick
54dce448a8 Added react-hooks lint rules
Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2023-02-19 23:09:35 -06:00
Servarr
3c915002c6 Automated API Docs update 2023-02-19 19:41:55 -06:00
Qstick
e32f8f4330 Remove unused tinytwitter library 2023-02-19 19:26:03 -06:00
Qstick
5abb5ada49 New: Ping Endpoint 2023-02-19 19:23:26 -06:00
Qstick
6579385110 Cleanup multi-platform code 2023-02-19 19:23:05 -06:00
Mark McDowall
1c6e5543df New: Return static response to requests while app is starting 2023-02-19 19:06:13 -06:00
Qstick
85737aacbe Bump version to 1.3.0 2023-02-19 18:14:12 -06:00
Servarr
30c3aedeb1 Automated API Docs update 2023-02-19 17:23:52 -06:00
Qstick
1640980e2b New: OnGrab Notifications 2023-02-19 17:16:05 -06:00
Bogdan
99bc56efb6 Fixed: (Indexers) Rate limit for download and auth 2023-02-19 18:54:17 +02:00
bakerboy448
04276eb587 Fixed: (Rarbg) Updated app_id per site request (#1447) 2023-02-19 18:23:18 +02:00
Bogdan
34c560fd3a Fixed: (CardigannBase) Remedy for casting strings to booleans 2023-02-19 17:07:25 +02:00
Bogdan
caa8bb05a7 Fixed: (Newznab API) Response with StatusCode 429 when limits are reached 2023-02-19 10:43:26 +02:00
Qstick
773e8ff1f4 Bump version to 1.2.2 2023-02-19 00:15:54 -06:00
187 changed files with 2929 additions and 2814 deletions

View File

@@ -9,7 +9,7 @@ variables:
testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '1.2.1'
majorVersion: '1.3.1'
minorVersion: $[counter('minorVersion', 1)]
prowlarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'

View File

@@ -39,6 +39,7 @@ module.exports = {
plugins: [
'filenames',
'react',
'react-hooks',
'simple-import-sort',
'import'
],
@@ -308,7 +309,9 @@ module.exports = {
'react/react-in-jsx-scope': 2,
'react/self-closing-comp': 2,
'react/sort-comp': 2,
'react/jsx-wrap-multilines': 2
'react/jsx-wrap-multilines': 2,
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'error'
},
overrides: [
{

View File

@@ -1,5 +1,5 @@
import PropTypes from 'prop-types';
import React, { Fragment, useEffect } from 'react';
import React, { Fragment, useCallback, useEffect } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import themes from 'Styles/Themes';
@@ -19,7 +19,8 @@ function createMapStateToProps() {
function ApplyTheme({ theme, children }) {
// Update the CSS Variables
function updateCSSVariables() {
const updateCSSVariables = useCallback(() => {
const arrayOfVariableKeys = Object.keys(themes[theme]);
const arrayOfVariableValues = Object.values(themes[theme]);
@@ -31,12 +32,12 @@ function ApplyTheme({ theme, children }) {
arrayOfVariableValues[index]
);
});
}
}, [theme]);
// On Component Mount and Component Update
useEffect(() => {
updateCSSVariables(theme);
}, [theme]);
}, [updateCSSVariables, theme]);
return <Fragment>{children}</Fragment>;
}

View File

@@ -30,10 +30,10 @@ function ConfirmModal(props) {
useEffect(() => {
if (isOpen) {
bindShortcut('enter', onConfirm);
} else {
unbindShortcut('enter', onConfirm);
return () => unbindShortcut('enter', onConfirm);
}
}, [onConfirm]);
}, [bindShortcut, unbindShortcut, isOpen, onConfirm]);
return (
<Modal

View File

@@ -253,7 +253,7 @@ class IndexerIndexRow extends Component {
className={styles.externalLink}
name={icons.EXTERNAL_LINK}
title={translate('Website')}
to={baseUrl.replace('api.', '')}
to={baseUrl.replace(/(:\/\/)api\./, '$1')}
/> : null
}

View File

@@ -71,6 +71,19 @@ class SearchIndexRow extends Component {
});
};
onSavePress = () => {
const {
downloadUrl,
fileName,
onSavePress
} = this.props;
onSavePress({
downloadUrl,
fileName
});
};
//
// Render
@@ -85,7 +98,6 @@ class SearchIndexRow extends Component {
publishDate,
title,
infoUrl,
downloadUrl,
indexer,
size,
files,
@@ -300,7 +312,7 @@ class SearchIndexRow extends Component {
className={styles.downloadLink}
name={icons.SAVE}
title={translate('Save')}
to={downloadUrl}
onPress={this.onSavePress}
/>
</VirtualTableRowCell>
);
@@ -323,6 +335,7 @@ SearchIndexRow.propTypes = {
ageMinutes: PropTypes.number.isRequired,
publishDate: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
fileName: PropTypes.string.isRequired,
infoUrl: PropTypes.string.isRequired,
downloadUrl: PropTypes.string.isRequired,
indexerId: PropTypes.number.isRequired,
@@ -335,6 +348,7 @@ SearchIndexRow.propTypes = {
indexerFlags: PropTypes.arrayOf(PropTypes.string).isRequired,
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
onGrabPress: PropTypes.func.isRequired,
onSavePress: PropTypes.func.isRequired,
isGrabbing: PropTypes.bool.isRequired,
isGrabbed: PropTypes.bool.isRequired,
grabError: PropTypes.string,

View File

@@ -51,7 +51,8 @@ class SearchIndexTable extends Component {
timeFormat,
selectedState,
onSelectedChange,
onGrabPress
onGrabPress,
onSavePress
} = this.props;
const release = items[rowIndex];
@@ -71,6 +72,7 @@ class SearchIndexTable extends Component {
longDateFormat={longDateFormat}
timeFormat={timeFormat}
onGrabPress={onGrabPress}
onSavePress={onSavePress}
/>
</VirtualTableRow>
);
@@ -134,6 +136,7 @@ SearchIndexTable.propTypes = {
timeFormat: PropTypes.string.isRequired,
onSortPress: PropTypes.func.isRequired,
onGrabPress: PropTypes.func.isRequired,
onSavePress: PropTypes.func.isRequired,
allSelected: PropTypes.bool.isRequired,
allUnselected: PropTypes.bool.isRequired,
selectedState: PropTypes.object.isRequired,

View File

@@ -1,6 +1,6 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { grabRelease, setReleasesSort } from 'Store/Actions/releaseActions';
import { grabRelease, saveRelease, setReleasesSort } from 'Store/Actions/releaseActions';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
import SearchIndexTable from './SearchIndexTable';
@@ -25,6 +25,9 @@ function createMapDispatchToProps(dispatch, props) {
},
onGrabPress(payload) {
dispatch(grabRelease(payload));
},
onSavePress(payload) {
dispatch(saveRelease(payload));
}
};
}

View File

@@ -56,17 +56,9 @@ class Notification extends Component {
id,
name,
onGrab,
onDownload,
onUpgrade,
onRename,
onDelete,
onHealthIssue,
onApplicationUpdate,
supportsOnGrab,
supportsOnDownload,
supportsOnUpgrade,
supportsOnRename,
supportsOnDelete,
supportsOnHealthIssue,
supportsOnApplicationUpdate
} = this.props;
@@ -88,34 +80,6 @@ class Notification extends Component {
</Label>
}
{
supportsOnDelete && onDelete &&
<Label kind={kinds.SUCCESS}>
{translate('OnDelete')}
</Label>
}
{
supportsOnDownload && onDownload &&
<Label kind={kinds.SUCCESS}>
{translate('OnImport')}
</Label>
}
{
supportsOnUpgrade && onDownload && onUpgrade &&
<Label kind={kinds.SUCCESS}>
{translate('OnUpgrade')}
</Label>
}
{
supportsOnRename && onRename &&
<Label kind={kinds.SUCCESS}>
{translate('OnRename')}
</Label>
}
{
supportsOnHealthIssue && onHealthIssue &&
<Label kind={kinds.SUCCESS}>
@@ -132,7 +96,7 @@ class Notification extends Component {
}
{
!onGrab && !onDownload && !onRename && !onHealthIssue && !onDelete && !onApplicationUpdate ?
!onGrab && !onHealthIssue && !onApplicationUpdate ?
<Label
kind={kinds.DISABLED}
outline={true}
@@ -167,17 +131,9 @@ Notification.propTypes = {
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
onGrab: PropTypes.bool.isRequired,
onDownload: PropTypes.bool.isRequired,
onUpgrade: PropTypes.bool.isRequired,
onRename: PropTypes.bool.isRequired,
onDelete: PropTypes.bool.isRequired,
onHealthIssue: PropTypes.bool.isRequired,
onApplicationUpdate: PropTypes.bool.isRequired,
supportsOnGrab: PropTypes.bool.isRequired,
supportsOnDownload: PropTypes.bool.isRequired,
supportsOnDelete: PropTypes.bool.isRequired,
supportsOnUpgrade: PropTypes.bool.isRequired,
supportsOnRename: PropTypes.bool.isRequired,
supportsOnHealthIssue: PropTypes.bool.isRequired,
supportsOnApplicationUpdate: PropTypes.bool.isRequired,
onConfirmDeleteNotification: PropTypes.func.isRequired

View File

@@ -15,8 +15,11 @@ function NotificationEventItems(props) {
} = props;
const {
onGrab,
onHealthIssue,
onApplicationUpdate,
supportsOnGrab,
includeManualGrabs,
supportsOnHealthIssue,
includeHealthWarnings,
supportsOnApplicationUpdate
@@ -31,6 +34,31 @@ function NotificationEventItems(props) {
link="https://wiki.servarr.com/prowlarr/settings#connections"
/>
<div className={styles.events}>
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="onGrab"
helpText={translate('OnGrabHelpText')}
isDisabled={!supportsOnGrab.value}
{...onGrab}
onChange={onInputChange}
/>
</div>
{
onGrab.value &&
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="includeManualGrabs"
helpText={translate('IncludeManualGrabsHelpText')}
isDisabled={!supportsOnGrab.value}
{...includeManualGrabs}
onChange={onInputChange}
/>
</div>
}
<div>
<FormInputGroup
type={inputTypes.CHECK}

View File

@@ -20,7 +20,7 @@ function PendingChangesModal(props) {
useEffect(() => {
bindShortcut('enter', onConfirm);
}, [onConfirm]);
}, [bindShortcut, onConfirm]);
return (
<Modal

View File

@@ -103,9 +103,6 @@ export default {
[SELECT_NOTIFICATION_SCHEMA]: (state, { payload }) => {
return selectProviderSchema(state, section, payload, (selectedSchema) => {
selectedSchema.onGrab = selectedSchema.supportsOnGrab;
selectedSchema.onDownload = selectedSchema.supportsOnDownload;
selectedSchema.onUpgrade = selectedSchema.supportsOnUpgrade;
selectedSchema.onRename = selectedSchema.supportsOnRename;
selectedSchema.onApplicationUpdate = selectedSchema.supportsOnApplicationUpdate;
return selectedSchema;

View File

@@ -1,3 +1,4 @@
import $ from 'jquery';
import { createAction } from 'redux-actions';
import { batchActions } from 'redux-batched-actions';
import { filterBuilderTypes, filterBuilderValueTypes, sortDirections } from 'Helpers/Props';
@@ -229,6 +230,7 @@ export const CANCEL_FETCH_RELEASES = 'releases/cancelFetchReleases';
export const SET_RELEASES_SORT = 'releases/setReleasesSort';
export const CLEAR_RELEASES = 'releases/clearReleases';
export const GRAB_RELEASE = 'releases/grabRelease';
export const SAVE_RELEASE = 'releases/saveRelease';
export const BULK_GRAB_RELEASES = 'release/bulkGrabReleases';
export const UPDATE_RELEASE = 'releases/updateRelease';
export const SET_RELEASES_FILTER = 'releases/setReleasesFilter';
@@ -243,6 +245,7 @@ export const cancelFetchReleases = createThunk(CANCEL_FETCH_RELEASES);
export const setReleasesSort = createAction(SET_RELEASES_SORT);
export const clearReleases = createAction(CLEAR_RELEASES);
export const grabRelease = createThunk(GRAB_RELEASE);
export const saveRelease = createThunk(SAVE_RELEASE);
export const bulkGrabReleases = createThunk(BULK_GRAB_RELEASES);
export const updateRelease = createAction(UPDATE_RELEASE);
export const setReleasesFilter = createAction(SET_RELEASES_FILTER);
@@ -304,6 +307,32 @@ export const actionHandlers = handleThunks({
});
},
[SAVE_RELEASE]: function(getState, payload, dispatch) {
const link = payload.downloadUrl;
const file = payload.fileName;
$.ajax({
url: link,
method: 'GET',
headers: {
'X-Prowlarr-Client': true
},
xhrFields: {
responseType: 'blob'
},
success: function(data) {
const a = document.createElement('a');
const url = window.URL.createObjectURL(data);
a.href = url;
a.download = file;
document.body.append(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
}
});
},
[BULK_GRAB_RELEASES]: function(getState, payload, dispatch) {
dispatch(set({
section,

View File

@@ -16,6 +16,11 @@ function addApiKey(ajaxOptions) {
ajaxOptions.headers['X-Api-Key'] = window.Prowlarr.apiKey;
}
function addUIHeader(ajaxOptions) {
ajaxOptions.headers = ajaxOptions.headers || {};
ajaxOptions.headers['X-Prowlarr-Client'] = true;
}
function addContentType(ajaxOptions) {
if (
ajaxOptions.contentType == null &&
@@ -42,6 +47,7 @@ export default function createAjaxRequest(originalAjaxOptions) {
if (isRelative(ajaxOptions)) {
addRootUrl(ajaxOptions);
addApiKey(ajaxOptions);
addUIHeader(ajaxOptions);
addContentType(ajaxOptions);
}

View File

@@ -105,6 +105,7 @@
"eslint-plugin-filenames": "1.3.2",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-react": "7.31.11",
"eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-simple-import-sort": "8.0.0",
"esprint": "3.6.0",
"file-loader": "6.2.0",

View File

@@ -278,7 +278,7 @@ namespace NzbDrone.Common.Test
[Test]
public void GetUpdateClientExePath()
{
GetIAppDirectoryInfo().GetUpdateClientExePath(PlatformType.DotNet).Should().BeEquivalentTo(@"C:\Temp\prowlarr_update\Prowlarr.Update.exe".AsOsAgnostic());
GetIAppDirectoryInfo().GetUpdateClientExePath().Should().BeEquivalentTo(@"C:\Temp\prowlarr_update\Prowlarr.Update".AsOsAgnostic().ProcessNameToExe());
}
[Test]

View File

@@ -9,6 +9,7 @@ namespace NzbDrone.Common.EnvironmentInfo
bool IsAdmin { get; }
bool IsWindowsService { get; }
bool IsWindowsTray { get; }
bool IsStarting { get; set; }
bool IsExiting { get; set; }
bool IsTray { get; }
RuntimeMode Mode { get; }

View File

@@ -2,13 +2,6 @@ using System;
namespace NzbDrone.Common.EnvironmentInfo
{
public enum PlatformType
{
DotNet = 0,
Mono = 1,
NetCore = 2
}
public interface IPlatformInfo
{
Version Version { get; }
@@ -16,36 +9,18 @@ namespace NzbDrone.Common.EnvironmentInfo
public class PlatformInfo : IPlatformInfo
{
private static PlatformType _platform;
private static Version _version;
static PlatformInfo()
{
_platform = PlatformType.NetCore;
_version = Environment.Version;
}
public static PlatformType Platform => _platform;
public static bool IsMono => Platform == PlatformType.Mono;
public static bool IsDotNet => Platform == PlatformType.DotNet;
public static bool IsNetCore => Platform == PlatformType.NetCore;
public static string PlatformName
{
get
{
if (IsDotNet)
{
return ".NET";
}
else if (IsMono)
{
return "Mono";
}
else
{
return ".NET Core";
}
return ".NET";
}
}

View File

@@ -19,6 +19,7 @@ namespace NzbDrone.Common.EnvironmentInfo
_logger = logger;
IsWindowsService = hostLifetime is WindowsServiceLifetime;
IsStarting = true;
// net6.0 will return Radarr.dll for entry assembly, we need the actual
// executable name (Radarr on linux). On mono this will return the location of
@@ -82,6 +83,7 @@ namespace NzbDrone.Common.EnvironmentInfo
public bool IsWindowsService { get; private set; }
public bool IsStarting { get; set; }
public bool IsExiting { get; set; }
public bool IsTray
{

View File

@@ -33,7 +33,7 @@ namespace NzbDrone.Common.Extensions
var info = new FileInfo(path.Trim());
//UNC
// UNC
if (OsInfo.IsWindows && info.FullName.StartsWith(@"\\"))
{
return info.FullName.TrimEnd('/', '\\', ' ');
@@ -166,7 +166,7 @@ namespace NzbDrone.Common.Extensions
var parentDirInfo = dirInfo.Parent;
if (parentDirInfo == null)
{
//Drive letter
// Drive letter
return dirInfo.Name.ToUpper();
}
@@ -238,9 +238,9 @@ namespace NzbDrone.Common.Extensions
return null;
}
public static string ProcessNameToExe(this string processName, PlatformType runtime)
public static string ProcessNameToExe(this string processName)
{
if (OsInfo.IsWindows || runtime != PlatformType.NetCore)
if (OsInfo.IsWindows)
{
processName += ".exe";
}
@@ -248,11 +248,6 @@ namespace NzbDrone.Common.Extensions
return processName;
}
public static string ProcessNameToExe(this string processName)
{
return processName.ProcessNameToExe(PlatformInfo.Platform);
}
public static string GetAppDataPath(this IAppFolderInfo appFolderInfo)
{
return appFolderInfo.AppDataFolder;
@@ -318,9 +313,9 @@ namespace NzbDrone.Common.Extensions
return Path.Combine(GetUpdatePackageFolder(appFolderInfo), UPDATE_CLIENT_FOLDER_NAME);
}
public static string GetUpdateClientExePath(this IAppFolderInfo appFolderInfo, PlatformType runtime)
public static string GetUpdateClientExePath(this IAppFolderInfo appFolderInfo)
{
return Path.Combine(GetUpdateSandboxFolder(appFolderInfo), UPDATE_CLIENT_EXE_NAME).ProcessNameToExe(runtime);
return Path.Combine(GetUpdateSandboxFolder(appFolderInfo), UPDATE_CLIENT_EXE_NAME).ProcessNameToExe();
}
public static string GetDatabase(this IAppFolderInfo appFolderInfo)

View File

@@ -257,5 +257,18 @@ namespace NzbDrone.Common.Extensions
{
return input.Contains(':') ? $"[{input}]" : input;
}
public static bool IsAllDigits(this string input)
{
foreach (var c in input)
{
if (c < '0' || c > '9')
{
return false;
}
}
return true;
}
}
}

View File

@@ -11,15 +11,13 @@ namespace NzbDrone.Common.Http
{
if (response.Headers.ContainsKey("Retry-After"))
{
var retryAfter = response.Headers["Retry-After"].ToString();
int seconds;
DateTime date;
var retryAfter = response.Headers["Retry-After"];
if (int.TryParse(retryAfter, out seconds))
if (int.TryParse(retryAfter, out var seconds))
{
RetryAfter = TimeSpan.FromSeconds(seconds);
}
else if (DateTime.TryParse(retryAfter, out date))
else if (DateTime.TryParse(retryAfter, out var date))
{
RetryAfter = date.ToUniversalTime() - DateTime.UtcNow;
}

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace NzbDrone.Common.Http
{

View File

@@ -68,9 +68,9 @@ namespace NzbDrone.Core.Test.IndexerTests.FileListTests
{
var results = Subject.GetSearchRequests(new MovieSearchCriteria { Categories = new[] { NewznabStandardCategory.MoviesSD.Id, NewznabStandardCategory.MoviesDVD.Id } });
results.GetAllTiers().Should().HaveCount(1);
results.Should().HaveCount(1);
var page = results.GetAllTiers().First().First();
var page = results.First();
page.Url.Query.Should().Contain("&category=1%2C2");
}
@@ -81,9 +81,9 @@ namespace NzbDrone.Core.Test.IndexerTests.FileListTests
_movieSearchCriteria.ImdbId = "0076759";
var results = Subject.GetSearchRequests(_movieSearchCriteria);
results.GetAllTiers().Should().HaveCount(1);
results.Should().HaveCount(1);
var page = results.GetAllTiers().First().First();
var page = results.First();
page.Url.Query.Should().Contain("type=imdb");
page.Url.Query.Should().Contain("query=tt0076759");
@@ -96,9 +96,9 @@ namespace NzbDrone.Core.Test.IndexerTests.FileListTests
var results = Subject.GetSearchRequests(_movieSearchCriteria);
results.GetAllTiers().Should().HaveCount(1);
results.Should().HaveCount(1);
var page = results.GetAllTiers().First().First();
var page = results.First();
page.Url.Query.Should().Contain("type=name");
page.Url.Query.Should().Contain("query=Star+Wars");

View File

@@ -76,9 +76,9 @@ namespace NzbDrone.Core.Test.IndexerTests.HDBitsTests
var results = Subject.GetSearchRequests(_movieSearchCriteria);
var imdbQuery = int.Parse(_movieSearchCriteria.ImdbId);
results.GetAllTiers().Should().HaveCount(1);
results.Should().HaveCount(1);
var page = results.GetAllTiers().First().First();
var page = results.First();
var encoding = HttpHeader.GetEncodingFromContentType(page.HttpRequest.Headers.ContentType);
@@ -95,9 +95,9 @@ namespace NzbDrone.Core.Test.IndexerTests.HDBitsTests
var results = Subject.GetSearchRequests(_tvSearchSeasonEpisodeCriteria);
var tvdbQuery = _tvSearchSeasonEpisodeCriteria.TvdbId;
results.GetAllTiers().Should().HaveCount(1);
results.Should().HaveCount(1);
var page = results.GetAllTiers().First().First();
var page = results.First();
var encoding = HttpHeader.GetEncodingFromContentType(page.HttpRequest.Headers.ContentType);
@@ -117,9 +117,9 @@ namespace NzbDrone.Core.Test.IndexerTests.HDBitsTests
var results = Subject.GetSearchRequests(_tvSearchDailyEpisodeCriteria);
var tvdbQuery = _tvSearchDailyEpisodeCriteria.TvdbId;
results.GetAllTiers().Should().HaveCount(1);
results.Should().HaveCount(1);
var page = results.GetAllTiers().First().First();
var page = results.First();
var encoding = HttpHeader.GetEncodingFromContentType(page.HttpRequest.Headers.ContentType);

View File

@@ -51,9 +51,9 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
_movieSearchCriteria.Offset = 0;
var results = Subject.GetSearchRequests(_movieSearchCriteria);
results.GetAllTiers().Should().HaveCount(1);
results.Should().HaveCount(1);
var pages = results.GetAllTiers().First().Take(3).ToList();
var pages = results.Take(3).ToList();
pages[0].Url.FullUri.Should().Contain("&offset=0");
}
@@ -63,9 +63,9 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
{
var results = Subject.GetSearchRequests(_movieSearchCriteria);
results.GetAllTiers().Should().HaveCount(1);
results.Should().HaveCount(1);
var pages = results.GetAllTiers().First().Take(500).ToList();
var pages = results.Take(500).ToList();
pages.Count.Should().BeLessThan(500);
}
@@ -77,9 +77,9 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
var results = Subject.GetSearchRequests(_movieSearchCriteria);
results.GetAllTiers().Should().HaveCount(1);
results.Should().HaveCount(1);
var page = results.GetAllTiers().First().First();
var page = results.First();
page.Url.Query.Should().NotContain("imdbid=0076759");
page.Url.Query.Should().Contain("q=Star");
@@ -92,9 +92,9 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
_capabilities.MovieSearchParams = new List<MovieSearchParam> { MovieSearchParam.Q, MovieSearchParam.ImdbId };
var results = Subject.GetSearchRequests(_movieSearchCriteria);
results.GetTier(0).Should().HaveCount(1);
results.Should().HaveCount(1);
var page = results.GetAllTiers().First().First();
var page = results.First();
page.Url.Query.Should().Contain("imdbid=0076759");
}
@@ -106,9 +106,9 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
_capabilities.MovieSearchParams = new List<MovieSearchParam> { MovieSearchParam.Q, MovieSearchParam.TmdbId };
var results = Subject.GetSearchRequests(_movieSearchCriteria);
results.GetTier(0).Should().HaveCount(1);
results.Should().HaveCount(1);
var page = results.GetAllTiers().First().First();
var page = results.First();
page.Url.Query.Should().Contain("tmdbid=11");
}
@@ -120,9 +120,9 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
_capabilities.MovieSearchParams = new List<MovieSearchParam> { MovieSearchParam.Q, MovieSearchParam.ImdbId, MovieSearchParam.TmdbId };
var results = Subject.GetSearchRequests(_movieSearchCriteria);
results.GetTier(0).Should().HaveCount(1);
results.Should().HaveCount(1);
var page = results.GetAllTiers().First().First();
var page = results.First();
page.Url.Query.Should().Contain("tmdbid=11");
page.Url.Query.Should().NotContain("imdbid=0076759");
@@ -136,9 +136,9 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
_capabilities.MovieSearchParams = new List<MovieSearchParam> { MovieSearchParam.Q, MovieSearchParam.ImdbId, MovieSearchParam.TmdbId };
var results = Subject.GetSearchRequests(_movieSearchCriteria);
results.GetTier(0).Should().HaveCount(1);
results.Should().HaveCount(1);
var page = results.GetTier(0).First().First();
var page = results.First();
page.Url.Query.Should().Contain("tmdbid=11");
page.Url.Query.Should().Contain("imdbid=0076759");
@@ -150,10 +150,9 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
_capabilities.MovieSearchParams = new List<MovieSearchParam> { MovieSearchParam.Q };
var results = Subject.GetSearchRequests(_movieSearchCriteria);
results.Tiers.Should().Be(1);
results.GetTier(0).Should().HaveCount(1);
results.Should().HaveCount(1);
var page = results.GetTier(0).First().First();
var page = results.First();
page.Url.Query.Should().Contain("q=");
}
@@ -167,7 +166,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
var results = Subject.GetSearchRequests(_movieSearchCriteria);
var page = results.GetTier(0).First().First();
var page = results.First();
page.Url.Query.Should().Contain("q=");
}
@@ -178,9 +177,9 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
_capabilities.MovieSearchParams = new List<MovieSearchParam> { MovieSearchParam.Q, MovieSearchParam.ImdbId, MovieSearchParam.TmdbId };
var results = Subject.GetSearchRequests(_movieSearchCriteria);
results.Tiers.Should().Be(1);
results.Should().HaveCount(1);
var pageTier2 = results.GetTier(0).First().First();
var pageTier2 = results.First();
pageTier2.Url.Query.Should().NotContain("tmdbid=11");
pageTier2.Url.Query.Should().NotContain("imdbid=0076759");
@@ -193,9 +192,9 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
_capabilities.TvSearchParams = new List<TvSearchParam> { TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep };
var results = Subject.GetSearchRequests(_tvSearchCriteria);
results.Tiers.Should().Be(1);
results.Should().HaveCount(1);
var pageTier = results.GetTier(0).First().First();
var pageTier = results.First();
pageTier.Url.Query.Should().Contain("season=00");
}

View File

@@ -9,7 +9,7 @@ using NUnit.Framework;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.Rarbg;
using NzbDrone.Core.Indexers.Definitions.Rarbg;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
@@ -23,14 +23,14 @@ namespace NzbDrone.Core.Test.IndexerTests.RarbgTests
[SetUp]
public void Setup()
{
Subject.Definition = new IndexerDefinition()
Subject.Definition = new IndexerDefinition
{
Name = "Rarbg",
Settings = new RarbgSettings()
};
Mocker.GetMock<IRarbgTokenProvider>()
.Setup(v => v.GetToken(It.IsAny<RarbgSettings>()))
.Setup(v => v.GetToken(It.IsAny<RarbgSettings>(), Subject.RateLimit))
.Returns("validtoken");
}
@@ -53,7 +53,7 @@ namespace NzbDrone.Core.Test.IndexerTests.RarbgTests
torrentInfo.Title.Should().Be("Sense8.S01E01.WEBRip.x264-FGT");
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
torrentInfo.DownloadUrl.Should().Be("magnet:?xt=urn:btih:d8bde635f573acb390c7d7e7efc1556965fdc802&dn=Sense8.S01E01.WEBRip.x264-FGT&tr=http%3A%2F%2Ftracker.trackerfix.com%3A80%2Fannounce&tr=udp%3A%2F%2F9.rarbg.me%3A2710&tr=udp%3A%2F%2F9.rarbg.to%3A2710&tr=udp%3A%2F%2Fopen.demonii.com%3A1337%2Fannounce");
torrentInfo.InfoUrl.Should().Be($"https://torrentapi.org/redirect_to_info.php?token=i5cx7b9agd&p=8_6_4_4_5_6__d8bde635f5&app_id={BuildInfo.AppName}");
torrentInfo.InfoUrl.Should().Be($"https://torrentapi.org/redirect_to_info.php?token=i5cx7b9agd&p=8_6_4_4_5_6__d8bde635f5&app_id=rralworP_{BuildInfo.Version}");
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2015-06-05 16:58:11 +0000").ToUniversalTime());
torrentInfo.Size.Should().Be(564198371);

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using FluentAssertions;
using FluentValidation.Results;
using NUnit.Framework;
@@ -56,6 +55,11 @@ namespace NzbDrone.Core.Test.NotificationTests
{
TestLogger.Info("OnApplicationUpdate was called");
}
public override void OnGrab(GrabMessage message)
{
TestLogger.Info("OnGrab was called");
}
}
private class TestNotificationWithNoEvents : NotificationBase<TestSetting>
@@ -76,6 +80,7 @@ namespace NzbDrone.Core.Test.NotificationTests
notification.SupportsOnHealthIssue.Should().BeTrue();
notification.SupportsOnApplicationUpdate.Should().BeTrue();
notification.SupportsOnGrab.Should().BeTrue();
}
[Test]
@@ -85,6 +90,7 @@ namespace NzbDrone.Core.Test.NotificationTests
notification.SupportsOnHealthIssue.Should().BeFalse();
notification.SupportsOnApplicationUpdate.Should().BeFalse();
notification.SupportsOnGrab.Should().BeFalse();
}
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Globalization;
using System.Threading;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class DateTimeUtilFixture : CoreTest
{
[TestCase("pt-BR")]
[TestCase("en-US")]
public void should_format_date_invariant(string culture)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo(culture);
var dateNow = DateTime.Now;
DateTimeUtil.FromUnknown(dateNow.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture))
.ToString(DateTimeUtil.Rfc1123ZPattern, CultureInfo.InvariantCulture)
.Should().Be(dateNow.ToString("ddd, dd MMM yyyy HH':'mm':'ss z", CultureInfo.InvariantCulture));
}
[TestCase("2022-08-08 02:07:39 -02:00", "2006-01-02 15:04:05 -07:00", "yyyy-MM-dd HH:mm:ss zzz", "2022-08-08 04:07:39 +00:00")]
[TestCase("2022-08-08 02:07:39 -02:00", "yyyy-MM-dd HH:mm:ss zzz", "yyyy-MM-dd HH:mm:ss zzz", "2022-08-08 04:07:39 +00:00")]
[TestCase("2022-08-08 -02:00", "2006-01-02 -07:00", "yyyy-MM-dd zzz", "2022-08-08 +00:00")]
[TestCase("2022-08-08 -02:00", "yyyy-MM-dd zzz", "yyyy-MM-dd zzz", "2022-08-08 +00:00")]
[TestCase("02:07:39 -02:00", "15:04:05 -07:00", "HH:mm:ss zzz", "04:07:39 +00:00")]
[TestCase("02:07:39 -02:00", "HH:mm:ss zzz", "HH:mm:ss zzz", "04:07:39 +00:00")]
[TestCase("-02:00", "zzz", "zzz", "+00:00")]
[TestCase("-02:00", "-07:00", "zzz", "+00:00")]
public void parse_datetime_golang(string dateInput, string format, string standardFormat, string expectedDate)
{
DateTimeUtil.ParseDateTimeGoLang(dateInput, format)
.ToUniversalTime()
.ToString(standardFormat, CultureInfo.InvariantCulture)
.Should().Be(expectedDate);
}
}
}

View File

@@ -52,5 +52,16 @@ namespace NzbDrone.Core.Test.ParserTests
{
ParseUtil.CoerceDouble(original).Should().Be(parsedInt);
}
[TestCase(null, null)]
[TestCase("", null)]
[TestCase("1", 1)]
[TestCase("1000 grabs", 1000)]
[TestCase("asdf123asdf", 123)]
[TestCase("asdf123asdf456asdf", 123)]
public void should_parse_long_from_string(string original, long? parsedInt)
{
ParseUtil.GetLongFromString(original).Should().Be(parsedInt);
}
}
}

View File

@@ -40,12 +40,11 @@ namespace NzbDrone.Core.Test.UpdateTests
}
[Test]
[Ignore("TODO No Updates On Server")]
public void should_get_recent_updates()
{
const string branch = "develop";
UseRealHttp();
var recent = Subject.GetRecentUpdates(branch, new Version(2, 0), null);
var recent = Subject.GetRecentUpdates(branch, new Version(1, 0), null);
var recentWithChanges = recent.Where(c => c.Changes != null);
recent.Should().NotBeEmpty();

View File

@@ -69,7 +69,7 @@ namespace NzbDrone.Core.Test.UpdateTests
.Returns(true);
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.FileExists(It.Is<string>(s => s.EndsWith("Prowlarr.Update.exe"))))
.Setup(v => v.FileExists(It.Is<string>(s => s.EndsWith("Prowlarr.Update".ProcessNameToExe()))))
.Returns(true);
_sandboxFolder = Mocker.GetMock<IAppFolderInfo>().Object.GetUpdateSandboxFolder();
@@ -165,7 +165,7 @@ namespace NzbDrone.Core.Test.UpdateTests
public void should_return_with_warning_if_updater_doesnt_exists()
{
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.FileExists(It.Is<string>(s => s.EndsWith("Prowlarr.Update.exe"))))
.Setup(v => v.FileExists(It.Is<string>(s => s.EndsWith("Prowlarr.Update".ProcessNameToExe()))))
.Returns(false);
Subject.Execute(new ApplicationUpdateCommand());

View File

@@ -0,0 +1,15 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(029)]
public class add_on_grab_to_notifications : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("Notifications").AddColumn("OnGrab").AsBoolean().WithDefaultValue(false);
Alter.Table("Notifications").AddColumn("IncludeManualGrabs").AsBoolean().WithDefaultValue(false).NotNullable();
}
}
}

View File

@@ -66,6 +66,7 @@ namespace NzbDrone.Core.Datastore
Mapper.Entity<NotificationDefinition>("Notifications").RegisterModel()
.Ignore(x => x.ImplementationName)
.Ignore(i => i.SupportsOnGrab)
.Ignore(i => i.SupportsOnHealthIssue)
.Ignore(i => i.SupportsOnApplicationUpdate);

View File

@@ -1,7 +1,6 @@
using System;
using System.Threading.Tasks;
using NLog;
using NzbDrone.Common.EnsureThat;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Common.Instrumentation.Extensions;
@@ -61,16 +60,17 @@ namespace NzbDrone.Core.Download
// Get the seed configuration for this release.
// remoteMovie.SeedConfiguration = _seedConfigProvider.GetSeedConfiguration(remoteMovie);
// Limit grabs to 2 per second.
if (release.DownloadUrl.IsNotNullOrWhiteSpace() && !release.DownloadUrl.StartsWith("magnet:"))
{
var url = new HttpUri(release.DownloadUrl);
_rateLimitService.WaitAndPulse(url.Host, TimeSpan.FromSeconds(2));
}
var indexer = _indexerFactory.GetInstance(_indexerFactory.Get(release.IndexerId));
var grabEvent = new IndexerDownloadEvent(release, true, source, host, release.Title, release.DownloadUrl)
{
DownloadClient = downloadClient.Name,
DownloadClientId = downloadClient.Definition.Id,
DownloadClientName = downloadClient.Definition.Name,
Redirect = redirect,
GrabTrigger = source == "Prowlarr" ? GrabTrigger.Manual : GrabTrigger.Api
};
string downloadClientId;
try
{
@@ -81,19 +81,20 @@ namespace NzbDrone.Core.Download
catch (ReleaseUnavailableException)
{
_logger.Trace("Release {0} no longer available on indexer.", release);
_eventAggregator.PublishEvent(new IndexerDownloadEvent(release.IndexerId, false, source, host, release.Title, release.DownloadUrl, redirect));
grabEvent.Successful = false;
_eventAggregator.PublishEvent(grabEvent);
throw;
}
catch (DownloadClientRejectedReleaseException)
{
_logger.Trace("Release {0} rejected by download client, possible duplicate.", release);
_eventAggregator.PublishEvent(new IndexerDownloadEvent(release.IndexerId, false, source, host, release.Title, release.DownloadUrl, redirect));
grabEvent.Successful = false;
_eventAggregator.PublishEvent(grabEvent);
throw;
}
catch (ReleaseDownloadException ex)
{
var http429 = ex.InnerException as TooManyRequestsException;
if (http429 != null)
if (ex.InnerException is TooManyRequestsException http429)
{
_indexerStatusService.RecordFailure(release.IndexerId, http429.RetryAfter);
}
@@ -102,14 +103,21 @@ namespace NzbDrone.Core.Download
_indexerStatusService.RecordFailure(release.IndexerId);
}
_eventAggregator.PublishEvent(new IndexerDownloadEvent(release.IndexerId, false, source, host, release.Title, release.DownloadUrl, redirect));
grabEvent.Successful = false;
_eventAggregator.PublishEvent(grabEvent);
throw;
}
_logger.ProgressInfo("Report sent to {0}. {1}", downloadClient.Definition.Name, downloadTitle);
_eventAggregator.PublishEvent(new IndexerDownloadEvent(release.IndexerId, true, source, host, release.Title, release.DownloadUrl, redirect));
if (!string.IsNullOrWhiteSpace(downloadClientId))
{
grabEvent.DownloadId = downloadClientId;
}
_eventAggregator.PublishEvent(grabEvent);
}
public async Task<byte[]> DownloadReport(string link, int indexerId, string source, string host, string title)
@@ -127,22 +135,35 @@ namespace NzbDrone.Core.Download
var success = false;
var downloadedBytes = Array.Empty<byte>();
var release = new ReleaseInfo
{
Title = title,
DownloadUrl = link,
IndexerId = indexerId,
Indexer = indexer.Definition.Name,
DownloadProtocol = indexer.Protocol
};
var grabEvent = new IndexerDownloadEvent(release, success, source, host, release.Title, release.DownloadUrl)
{
GrabTrigger = source == "Prowlarr" ? GrabTrigger.Manual : GrabTrigger.Api
};
try
{
downloadedBytes = await indexer.Download(url);
_indexerStatusService.RecordSuccess(indexerId);
success = true;
grabEvent.Successful = true;
}
catch (ReleaseUnavailableException)
{
_logger.Trace("Release {0} no longer available on indexer.", link);
_eventAggregator.PublishEvent(new IndexerDownloadEvent(indexerId, success, source, host, title, url.AbsoluteUri));
_eventAggregator.PublishEvent(grabEvent);
throw;
}
catch (ReleaseDownloadException ex)
{
var http429 = ex.InnerException as TooManyRequestsException;
if (http429 != null)
if (ex.InnerException is TooManyRequestsException http429)
{
_indexerStatusService.RecordFailure(indexerId, http429.RetryAfter);
}
@@ -151,19 +172,36 @@ namespace NzbDrone.Core.Download
_indexerStatusService.RecordFailure(indexerId);
}
_eventAggregator.PublishEvent(new IndexerDownloadEvent(indexerId, success, source, host, title, url.AbsoluteUri));
_eventAggregator.PublishEvent(grabEvent);
throw;
}
_logger.Trace("Downloaded {0} bytes from {1}", downloadedBytes.Length, link);
_eventAggregator.PublishEvent(new IndexerDownloadEvent(indexerId, success, source, host, title, url.AbsoluteUri));
_eventAggregator.PublishEvent(grabEvent);
return downloadedBytes;
}
public void RecordRedirect(string link, int indexerId, string source, string host, string title)
{
_eventAggregator.PublishEvent(new IndexerDownloadEvent(indexerId, true, source, host, title, link, true));
var indexer = _indexerFactory.GetInstance(_indexerFactory.Get(indexerId));
var release = new ReleaseInfo
{
Title = title,
DownloadUrl = link,
IndexerId = indexerId,
Indexer = indexer.Definition.Name,
DownloadProtocol = indexer.Protocol
};
var grabEvent = new IndexerDownloadEvent(release, true, source, host, release.Title, release.DownloadUrl)
{
Redirect = true,
GrabTrigger = source == "Prowlarr" ? GrabTrigger.Manual : GrabTrigger.Api
};
_eventAggregator.PublishEvent(grabEvent);
}
}
}

View File

@@ -52,7 +52,7 @@ namespace NzbDrone.Core.HealthCheck
.AddQueryParam("version", BuildInfo.Version)
.AddQueryParam("os", OsInfo.Os.ToString().ToLowerInvariant())
.AddQueryParam("arch", RuntimeInformation.OSArchitecture)
.AddQueryParam("runtime", PlatformInfo.Platform.ToString().ToLowerInvariant())
.AddQueryParam("runtime", "netcore")
.AddQueryParam("branch", _configFileProvider.Branch)
.Build();
try

View File

@@ -19,6 +19,7 @@ namespace NzbDrone.Core.History
List<History> Since(DateTime date, HistoryEventType? eventType);
void Cleanup(int days);
int CountSince(int indexerId, DateTime date, List<HistoryEventType> eventTypes);
History FindFirstForIndexerSince(int indexerId, DateTime date, List<HistoryEventType> eventTypes, int limit);
}
public class HistoryRepository : BasicRepository<History>, IHistoryRepository
@@ -115,5 +116,24 @@ namespace NzbDrone.Core.History
return conn.ExecuteScalar<int>(sql.RawSql, sql.Parameters);
}
}
public History FindFirstForIndexerSince(int indexerId, DateTime date, List<HistoryEventType> eventTypes, int limit)
{
var intEvents = eventTypes.Select(t => (int)t).ToList();
var builder = Builder()
.Where<History>(x => x.IndexerId == indexerId)
.Where<History>(x => x.Date >= date)
.Where<History>(x => intEvents.Contains((int)x.EventType));
var query = Query(builder);
if (limit > 0)
{
query = query.OrderByDescending(h => h.Date).Take(limit).ToList();
}
return query.MinBy(h => h.Date);
}
}
}

View File

@@ -27,6 +27,7 @@ namespace NzbDrone.Core.History
List<History> Between(DateTime start, DateTime end);
List<History> Since(DateTime date, HistoryEventType? eventType);
int CountSince(int indexerId, DateTime date, List<HistoryEventType> eventTypes);
History FindFirstForIndexerSince(int indexerId, DateTime date, List<HistoryEventType> eventTypes, int limit);
}
public class HistoryService : IHistoryService,
@@ -121,7 +122,7 @@ namespace NzbDrone.Core.History
{
Date = DateTime.UtcNow,
IndexerId = message.IndexerId,
EventType = message.Query.RssSearch ? HistoryEventType.IndexerRss : HistoryEventType.IndexerQuery,
EventType = message.Query.IsRssSearch ? HistoryEventType.IndexerRss : HistoryEventType.IndexerQuery,
Successful = message.QueryResult.Response?.StatusCode == HttpStatusCode.OK
};
@@ -184,7 +185,7 @@ namespace NzbDrone.Core.History
var history = new History
{
Date = DateTime.UtcNow,
IndexerId = message.IndexerId,
IndexerId = message.Release.IndexerId,
EventType = HistoryEventType.ReleaseGrabbed,
Successful = message.Successful
};
@@ -232,5 +233,10 @@ namespace NzbDrone.Core.History
{
return _historyRepository.CountSince(indexerId, date, eventTypes);
}
public History FindFirstForIndexerSince(int indexerId, DateTime date, List<HistoryEventType> eventTypes, int limit)
{
return _historyRepository.FindFirstForIndexerSince(indexerId, date, eventTypes, limit);
}
}
}

View File

@@ -10,6 +10,15 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
public int? Year { get; set; }
public string Genre { get; set; }
public override bool RssSearch => SearchTerm.IsNullOrWhiteSpace() && Author.IsNullOrWhiteSpace() && Title.IsNullOrWhiteSpace();
public override bool IsRssSearch =>
SearchTerm.IsNullOrWhiteSpace() &&
!IsIdSearch;
public override bool IsIdSearch =>
Author.IsNotNullOrWhiteSpace() ||
Title.IsNotNullOrWhiteSpace() ||
Publisher.IsNotNullOrWhiteSpace() ||
Genre.IsNotNullOrWhiteSpace() ||
Year.HasValue;
}
}

View File

@@ -13,7 +13,17 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
public int? Year { get; set; }
public string Genre { get; set; }
public override bool RssSearch => SearchTerm.IsNullOrWhiteSpace() && ImdbId.IsNullOrWhiteSpace() && !TmdbId.HasValue && !TraktId.HasValue;
public override bool IsRssSearch =>
SearchTerm.IsNullOrWhiteSpace() &&
!IsIdSearch;
public override bool IsIdSearch =>
ImdbId.IsNotNullOrWhiteSpace() ||
Genre.IsNotNullOrWhiteSpace() ||
TmdbId.HasValue ||
TraktId.HasValue ||
DoubanId.HasValue ||
Year.HasValue;
public string FullImdbId => ParseUtil.GetFullImdbId(ImdbId);

View File

@@ -11,6 +11,16 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
public string Track { get; set; }
public int? Year { get; set; }
public override bool RssSearch => SearchTerm.IsNullOrWhiteSpace() && Album.IsNullOrWhiteSpace() && Artist.IsNullOrWhiteSpace() && Label.IsNullOrWhiteSpace();
public override bool IsRssSearch =>
SearchTerm.IsNullOrWhiteSpace() &&
!IsIdSearch;
public override bool IsIdSearch =>
Album.IsNotNullOrWhiteSpace() ||
Artist.IsNotNullOrWhiteSpace() ||
Label.IsNotNullOrWhiteSpace() ||
Genre.IsNotNullOrWhiteSpace() ||
Track.IsNotNullOrWhiteSpace() ||
Year.HasValue;
}
}

View File

@@ -15,16 +15,18 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
public string SearchTerm { get; set; }
public int[] Categories { get; set; }
public string SearchType { get; set; }
public int? Limit { get; set; }
public int? Offset { get; set; }
public int Limit { get; set; }
public int Offset { get; set; }
public string Source { get; set; }
public string Host { get; set; }
public override string ToString() => $"{SearchQuery}, Offset: {Offset ?? 0}, Limit: {Limit ?? 0}, Categories: [{string.Join(", ", Categories)}]";
public override string ToString() => $"{SearchQuery}, Offset: {Offset}, Limit: {Limit}, Categories: [{string.Join(", ", Categories)}]";
public virtual string SearchQuery => $"Term: [{SearchTerm}]";
public virtual bool RssSearch => SearchTerm.IsNullOrWhiteSpace();
public virtual bool IsRssSearch => SearchTerm.IsNullOrWhiteSpace();
public virtual bool IsIdSearch => false;
public string SanitizedSearchTerm => GetSanitizedTerm(SearchTerm);

View File

@@ -26,7 +26,20 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
public string FullImdbId => ParseUtil.GetFullImdbId(ImdbId);
public override bool RssSearch => SearchTerm.IsNullOrWhiteSpace() && ImdbId.IsNullOrWhiteSpace() && !TvdbId.HasValue && !RId.HasValue && !TraktId.HasValue && !TvMazeId.HasValue;
public override bool IsRssSearch =>
SearchTerm.IsNullOrWhiteSpace() &&
!IsIdSearch;
public override bool IsIdSearch =>
Episode.IsNotNullOrWhiteSpace() ||
ImdbId.IsNotNullOrWhiteSpace() ||
Season.HasValue ||
TvdbId.HasValue ||
RId.HasValue ||
TraktId.HasValue ||
TvMazeId.HasValue ||
TmdbId.HasValue ||
DoubanId.HasValue;
public override string SearchQuery
{

View File

@@ -138,8 +138,8 @@ namespace NzbDrone.Core.IndexerSearch
spec.SearchTerm = query.q;
spec.SearchType = query.t;
spec.Limit = query.limit;
spec.Offset = query.offset;
spec.Limit = query.limit ?? 100;
spec.Offset = query.offset ?? 0;
spec.Source = query.source;
spec.Host = query.host;

View File

@@ -29,7 +29,7 @@ namespace NzbDrone.Core.IndexerVersions
/* 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 = 8;
private const int DEFINITION_VERSION = 9;
// Used when moving yml to C#
private readonly List<string> _definitionBlocklist = new ()

View File

@@ -100,45 +100,29 @@ namespace NzbDrone.Core.Indexers.Definitions
_capabilities = capabilities;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories)

View File

@@ -194,49 +194,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}"));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}");
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}"));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}");
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}"));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}");
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}"));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}");
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}"));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}");
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -107,34 +107,30 @@ namespace NzbDrone.Core.Indexers.Definitions
{
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
=> GetRequestWithSearchType(searchCriteria, "anime");
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
=> GetRequestWithSearchType(searchCriteria, "music");
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
=> GetRequestWithSearchType(searchCriteria, "anime");
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
=> GetRequestWithSearchType(searchCriteria, "anime");
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
=> GetRequestWithSearchType(searchCriteria, "anime");
private IndexerPageableRequestChain GetRequestWithSearchType(SearchCriteriaBase searchCriteria, string searchType)
private IEnumerable<IndexerRequest> GetRequestWithSearchType(SearchCriteriaBase searchCriteria, string searchType)
{
var pageableRequests = new IndexerPageableRequestChain();
// TODO: Remove this once Prowlarr has proper support for non Pageable Indexers and can tell Sonarr that indexer doesn't support pagination in a proper way, for now just return empty release list on all request containing an offset
if (searchCriteria.Offset is > 0)
{
return pageableRequests;
return new List<IndexerRequest>();
}
pageableRequests.Add(GetRequest(searchType, searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
return pageableRequests;
return GetRequest(searchType, searchCriteria.SanitizedSearchTerm, searchCriteria.Categories);
}
private IEnumerable<IndexerRequest> GetRequest(string searchType, string term, int[] categories)

View File

@@ -164,49 +164,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -99,43 +99,31 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return new IndexerRequest(requestUrl, HttpAccept.Html);
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}"));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}");
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}"));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}");
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}"));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}");
}
// Animedia doesn't support music, but this function required by interface
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
// Animedia doesn't support books, but this function required by interface
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -146,45 +146,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
return pageableRequests;
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
return pageableRequests;
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -192,37 +192,29 @@ public class AudioBookBayRequestGenerator : IIndexerRequestGenerator
_capabilities = capabilities;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}"));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}");
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}"));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}");
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term)

View File

@@ -76,7 +76,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var parameters = GetBasicSearchParameters(searchCriteria.Categories, searchCriteria.Genre);
@@ -93,23 +93,19 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
parameters.Add("search", GetSearchTerm(searchCriteria.SanitizedSearchTerm).Trim());
}
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(parameters));
return pageableRequests;
return GetRequest(parameters);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var parameters = GetBasicSearchParameters(searchCriteria.Categories, null);
parameters.Add("search", GetSearchTerm(searchCriteria.SanitizedSearchTerm).Trim());
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(parameters));
return pageableRequests;
return GetRequest(parameters);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var parameters = GetBasicSearchParameters(searchCriteria.Categories, searchCriteria.Genre);
@@ -128,12 +124,10 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
parameters.Add("search", GetSearchTerm(searchCriteria.SanitizedTvSearchString).Trim());
}
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(parameters));
return pageableRequests;
return GetRequest(parameters);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
throw new NotImplementedException();
}
@@ -141,15 +135,13 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
// hook to adjust the search term
protected virtual string GetSearchTerm(string term) => term;
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var parameters = GetBasicSearchParameters(searchCriteria.Categories, null);
parameters.Add("search", GetSearchTerm(searchCriteria.SanitizedSearchTerm).Trim());
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(parameters));
return pageableRequests;
return GetRequest(parameters);
}
}
}

View File

@@ -177,49 +177,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -178,49 +178,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm)));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm));
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm)));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm));
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm)));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm));
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm)));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm));
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm)));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm));
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -120,49 +120,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return indexerRequest;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId, searchCriteria.TmdbId.GetValueOrDefault()));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId, searchCriteria.TmdbId.GetValueOrDefault());
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -90,7 +90,7 @@ namespace NzbDrone.Core.Indexers.Definitions
{ "adv_sort", "date" },
{ "q", term },
{ "m", searchCriteria.Offset.ToString() },
{ "max", searchCriteria.Limit?.ToString() ?? "100" }
{ "max", searchCriteria.Limit.ToString() ?? "100" }
};
var searchUrl = string.Format("{0}/?{1}", Settings.BaseUrl.TrimEnd('/'), qc.GetQueryString());
@@ -100,49 +100,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -129,49 +129,29 @@ namespace NzbDrone.Core.Indexers.Definitions
}
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -34,31 +34,29 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
yield return new IndexerRequest(builder.Build());
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new BroadcastheNetTorrentQuery();
var searchString = searchCriteria.SearchTerm != null ? searchCriteria.SearchTerm : "";
var btnResults = searchCriteria.Limit.GetValueOrDefault();
var btnResults = searchCriteria.Limit;
if (btnResults == 0)
{
btnResults = (int)Capabilities.LimitsDefault;
}
var btnOffset = searchCriteria.Offset.GetValueOrDefault();
var btnOffset = searchCriteria.Offset;
if (searchCriteria.TvdbId > 0)
{
@@ -93,25 +91,21 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
// Neither a season only search nor daily nor standard, fall back to query
parameters.Search = searchString.Replace(" ", "%");
pageableRequests.Add(GetPagedRequests(parameters, btnResults, btnOffset));
return pageableRequests;
return GetPagedRequests(parameters, btnResults, btnOffset);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new BroadcastheNetTorrentQuery();
var searchString = searchCriteria.SearchTerm != null ? searchCriteria.SearchTerm : "";
var btnResults = searchCriteria.Limit.GetValueOrDefault();
var btnResults = searchCriteria.Limit;
if (btnResults == 0)
{
btnResults = (int)Capabilities.LimitsDefault;
@@ -119,11 +113,9 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
parameters.Search = searchString.Replace(" ", "%");
var btnOffset = searchCriteria.Offset.GetValueOrDefault();
var btnOffset = searchCriteria.Offset;
pageableRequests.Add(GetPagedRequests(parameters, btnResults, btnOffset));
return pageableRequests;
return GetPagedRequests(parameters, btnResults, btnOffset);
}
}
}

View File

@@ -1,17 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Exceptions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.IndexerVersions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
@@ -29,10 +28,6 @@ namespace NzbDrone.Core.Indexers.Cardigann
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
// Page size is different per indexer, setting to 1 ensures we don't break out of paging logic
// thinking its a partial page and instead all search_path requests are run for each indexer
public override int PageSize => 1;
public override TimeSpan RateLimit
{
get
@@ -48,12 +43,28 @@ namespace NzbDrone.Core.Indexers.Cardigann
}
}
public override int PageSize
{
get
{
var definition = _definitionService.GetCachedDefinition(Settings.DefinitionFile);
if (definition.Search != null && definition.Search.PageSize > 0)
{
return definition.Search.PageSize;
}
return 0;
}
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
var generator = _generatorCache.Get(Settings.DefinitionFile, () =>
new CardigannRequestGenerator(_configService,
_definitionService.GetCachedDefinition(Settings.DefinitionFile),
_logger)
_logger,
RateLimit)
{
HttpClient = _httpClient,
Definition = Definition,
@@ -79,6 +90,37 @@ namespace NzbDrone.Core.Indexers.Cardigann
};
}
protected override IList<ReleaseInfo> CleanupReleases(IEnumerable<ReleaseInfo> releases, SearchCriteriaBase searchCriteria)
{
var cleanReleases = base.CleanupReleases(releases, searchCriteria);
if (_definitionService.GetCachedDefinition(Settings.DefinitionFile).Search?.Rows?.Filters?.Any(x => x.Name == "andmatch") ?? false)
{
cleanReleases = FilterReleasesByQuery(releases, searchCriteria).ToList();
}
// Only take the request results using Offset and Limit from the search
var pageSize = PageSize;
if (pageSize > 0)
{
var minPage = searchCriteria.Offset / pageSize;
var firstResult = searchCriteria.Offset - (pageSize * minPage);
cleanReleases = cleanReleases
.Skip(firstResult)
.Take(searchCriteria.Limit).ToList();
}
else
{
cleanReleases = cleanReleases
.Skip(searchCriteria.Offset)
.Take(searchCriteria.Limit).ToList();
}
return cleanReleases;
}
protected override IDictionary<string, string> GetCookies()
{
if (Settings.ExtraFieldData.TryGetValue("cookie", out var cookies))
@@ -117,8 +159,8 @@ namespace NzbDrone.Core.Indexers.Cardigann
{
var defaultSettings = new List<SettingsField>
{
new SettingsField { Name = "username", Label = "Username", Type = "text" },
new SettingsField { Name = "password", Label = "Password", Type = "password" }
new () { Name = "username", Label = "Username", Type = "text" },
new () { Name = "password", Label = "Password", Type = "password" }
};
var settings = definition.Settings ?? defaultSettings;
@@ -180,63 +222,15 @@ namespace NzbDrone.Core.Indexers.Cardigann
await generator.DoLogin();
}
public override async Task<byte[]> Download(Uri link)
protected override async Task<HttpRequest> GetDownloadRequest(Uri link)
{
var generator = (CardigannRequestGenerator)GetRequestGenerator();
var request = await generator.DownloadRequest(link);
if (request.Url.Scheme == "magnet")
{
ValidateMagnet(request.Url.FullUri);
return Encoding.UTF8.GetBytes(request.Url.FullUri);
}
request.AllowAutoRedirect = true;
var downloadBytes = Array.Empty<byte>();
try
{
var response = await _httpClient.ExecuteProxiedAsync(request, Definition);
downloadBytes = response.ResponseData;
}
catch (HttpException ex)
{
if (ex.Response.StatusCode == HttpStatusCode.NotFound)
{
_logger.Error(ex, "Downloading torrent file for release failed since it no longer exists ({0})", request.Url.FullUri);
throw new ReleaseUnavailableException("Downloading torrent failed", ex);
}
if (ex.Response.StatusCode == HttpStatusCode.TooManyRequests)
{
_logger.Error("API Grab Limit reached for {0}", request.Url.FullUri);
}
else
{
_logger.Error(ex, "Downloading torrent file for release failed ({0})", request.Url.FullUri);
}
throw new ReleaseDownloadException("Downloading torrent failed", ex);
}
catch (WebException ex)
{
_logger.Error(ex, "Downloading torrent file for release failed ({0})", request.Url.FullUri);
throw new ReleaseDownloadException("Downloading torrent failed", ex);
}
catch (Exception)
{
_indexerStatusService.RecordFailure(Definition.Id);
_logger.Error("Downloading torrent failed");
throw;
}
ValidateTorrent(downloadBytes);
return downloadBytes;
return request;
}
protected override async Task Test(List<ValidationFailure> failures)

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Text;
@@ -300,7 +301,12 @@ namespace NzbDrone.Core.Indexers.Cardigann
}
else if (setting.Type == "checkbox")
{
variables[name] = ((bool)value) ? ".True" : null;
if (value is string stringValue && bool.TryParse(stringValue, out var result))
{
value = result;
}
variables[name] = (bool)value ? ".True" : null;
}
else if (setting.Type == "select")
{
@@ -328,12 +334,12 @@ namespace NzbDrone.Core.Indexers.Cardigann
}
else
{
throw new NotSupportedException();
throw new NotSupportedException($"Type {setting.Type} is not supported.");
}
if (setting.Type != "password" && setting.Name != "apikey" && setting.Name != "rsskey" && indexerLogging)
if (setting.Type != "password" && setting.Name != "apikey" && setting.Name != "rsskey" && indexerLogging && variables.ContainsKey(name))
{
_logger.Debug($"Setting {setting.Name} to {variables[name]}");
_logger.Debug($"Setting {setting.Name} to {variables[name].ToJson()}");
}
}
@@ -344,11 +350,13 @@ namespace NzbDrone.Core.Indexers.Cardigann
public string ApplyGoTemplateText(string template, Dictionary<string, object> variables = null, TemplateTextModifier modifier = null)
{
if (variables == null)
if (template.IsNullOrWhiteSpace() || !template.Contains("{{"))
{
variables = GetBaseTemplateVariables();
return template;
}
variables ??= GetBaseTemplateVariables();
// handle re_replace expression
// Example: {{ re_replace .Query.Keywords "[^a-zA-Z0-9]+" "%" }}
var reReplaceRegex = new Regex(@"{{\s*re_replace\s+(\..+?)\s+""(.*?)""\s+""(.*?)""\s*}}");
@@ -606,10 +614,11 @@ namespace NzbDrone.Core.Indexers.Cardigann
case "timeparse":
case "dateparse":
var layout = (string)filter.Args;
try
{
var date = DateTimeUtil.ParseDateTimeGoLang(data, layout);
data = date.ToString(DateTimeUtil.Rfc1123ZPattern);
data = date.ToString(DateTimeUtil.Rfc1123ZPattern, CultureInfo.InvariantCulture);
}
catch (InvalidDateException ex)
{
@@ -650,15 +659,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
break;
case "trim":
var cutset = (string)filter.Args;
if (cutset != null)
{
data = data.Trim(cutset[0]);
}
else
{
data = data.Trim();
}
data = cutset != null ? data.Trim(cutset[0]) : data.Trim();
break;
case "prepend":
var prependstr = (string)filter.Args;
@@ -688,10 +689,10 @@ namespace NzbDrone.Core.Indexers.Cardigann
break;
case "timeago":
case "reltime":
data = DateTimeUtil.FromTimeAgo(data).ToString(DateTimeUtil.Rfc1123ZPattern);
data = DateTimeUtil.FromTimeAgo(data).ToString(DateTimeUtil.Rfc1123ZPattern, CultureInfo.InvariantCulture);
break;
case "fuzzytime":
data = DateTimeUtil.FromUnknown(data).ToString(DateTimeUtil.Rfc1123ZPattern);
data = DateTimeUtil.FromUnknown(data).ToString(DateTimeUtil.Rfc1123ZPattern, CultureInfo.InvariantCulture);
break;
case "validfilename":
data = StringUtil.MakeValidFileName(data, '_', false);
@@ -739,18 +740,20 @@ namespace NzbDrone.Core.Indexers.Cardigann
// for debugging
var debugData = data.Replace("\r", "\\r").Replace("\n", "\\n").Replace("\xA0", "\\xA0");
var strTag = (string)filter.Args;
if (strTag != null)
{
strTag = string.Format("({0}):", strTag);
}
else
{
strTag = ":";
}
strTag = strTag != null ? $"({strTag}):" : ":";
_logger.Debug(string.Format("CardigannIndexer ({0}): strdump{1} {2}", _definition.Id, strTag, debugData));
_logger.Debug($"CardigannIndexer ({_definition.Id}): strdump{strTag} {debugData}");
break;
case "validate":
char[] delimiters = { ',', ' ', '/', ')', '(', '.', ';', '[', ']', '"', '|', ':' };
var args = (string)filter.Args;
var argsList = args.ToLower().Split(delimiters, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
var validList = argsList.ToList();
var validIntersect = validList.Intersect(data.ToLower().Split(delimiters, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)).ToList();
data = string.Join(", ", validIntersect);
break;
default:
_logger.Error($"CardigannIndexer ({_definition.Id}): Unsupported field filter: {filter.Name}");
break;
}
}
@@ -758,8 +761,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
return data;
}
protected Dictionary<string, string> ParseCustomHeaders(Dictionary<string, List<string>> customHeaders,
Dictionary<string, object> variables)
protected Dictionary<string, string> ParseCustomHeaders(Dictionary<string, List<string>> customHeaders, Dictionary<string, object> variables)
{
if (customHeaders == null)
{

View File

@@ -102,6 +102,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
public List<ErrorBlock> Error { get; set; }
public PageTestBlock Test { get; set; }
public CaptchaBlock Captcha { get; set; }
public Dictionary<string, List<string>> Headers { get; set; }
}
public class ErrorBlock
@@ -141,6 +142,9 @@ namespace NzbDrone.Core.Indexers.Cardigann
public class SearchBlock
{
public int PageSize { get; set; }
public int FirstPageNumber { get; set; }
public bool AllowEmptyInputs { get; set; }
public string Path { get; set; }
public List<SearchPathBlock> Paths { get; set; }
public Dictionary<string, List<string>> Headers { get; set; }
@@ -182,20 +186,21 @@ namespace NzbDrone.Core.Indexers.Cardigann
public string Method { get; set; }
public BeforeBlock Before { get; set; }
public InfohashBlock Infohash { get; set; }
public Dictionary<string, List<string>> Headers { get; set; }
}
public class InfohashBlock
{
public SelectorField Hash { get; set; }
public SelectorField Title { get; set; }
public bool UseBeforeResponse { get; set; }
public bool Usebeforeresponse { get; set; }
}
public class SelectorField
{
public string Selector { get; set; }
public string Attribute { get; set; }
public bool UseBeforeResponse { get; set; }
public bool Usebeforeresponse { get; set; }
public List<FilterBlock> Filters { get; set; }
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
@@ -72,6 +73,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
}
var parsedJson = JToken.Parse(results);
if (parsedJson == null)
{
throw new IndexerException(indexerResponse, "Error Parsing Json Response");
@@ -80,12 +82,10 @@ namespace NzbDrone.Core.Indexers.Cardigann
if (search.Rows.Count != null)
{
var countVal = HandleJsonSelector(search.Rows.Count, parsedJson, variables);
if (int.TryParse(countVal, out var count))
if (int.TryParse(countVal, out var count) && count < 1)
{
if (count < 1)
{
return releases;
}
return releases;
}
}
@@ -165,205 +165,191 @@ namespace NzbDrone.Core.Indexers.Cardigann
}
else
{
try
IHtmlCollection<IElement> rowsDom;
if (request.SearchPath.Response != null && request.SearchPath.Response.Type.Equals("xml"))
{
IHtmlCollection<IElement> rowsDom;
var searchResultParser = new XmlParser();
var searchResultDocument = searchResultParser.ParseDocument(results);
if (request.SearchPath.Response != null && request.SearchPath.Response.Type.Equals("xml"))
if (search.Preprocessingfilters != null)
{
var searchResultParser = new XmlParser();
var searchResultDocument = searchResultParser.ParseDocument(results);
if (search.Preprocessingfilters != null)
{
results = ApplyFilters(results, search.Preprocessingfilters, variables);
searchResultDocument = searchResultParser.ParseDocument(results);
_logger.Trace(string.Format("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results));
}
var rowsSelector = ApplyGoTemplateText(search.Rows.Selector, variables);
rowsDom = searchResultDocument.QuerySelectorAll(rowsSelector);
}
else
{
var searchResultParser = new HtmlParser();
var searchResultDocument = searchResultParser.ParseDocument(results);
if (search.Preprocessingfilters != null)
{
results = ApplyFilters(results, search.Preprocessingfilters, variables);
searchResultDocument = searchResultParser.ParseDocument(results);
_logger.Trace(string.Format("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results));
}
var rowsSelector = ApplyGoTemplateText(search.Rows.Selector, variables);
rowsDom = searchResultDocument.QuerySelectorAll(rowsSelector);
results = ApplyFilters(results, search.Preprocessingfilters, variables);
searchResultDocument = searchResultParser.ParseDocument(results);
_logger.Trace(string.Format("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results));
}
var rows = new List<IElement>();
foreach (var rowDom in rowsDom)
var rowsSelector = ApplyGoTemplateText(search.Rows.Selector, variables);
rowsDom = searchResultDocument.QuerySelectorAll(rowsSelector);
}
else
{
var searchResultParser = new HtmlParser();
var searchResultDocument = searchResultParser.ParseDocument(results);
if (search.Preprocessingfilters != null)
{
rows.Add(rowDom);
results = ApplyFilters(results, search.Preprocessingfilters, variables);
searchResultDocument = searchResultParser.ParseDocument(results);
_logger.Trace(string.Format("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results));
}
// merge following rows for After selector
var after = search.Rows.After;
if (after > 0)
var rowsSelector = ApplyGoTemplateText(search.Rows.Selector, variables);
rowsDom = searchResultDocument.QuerySelectorAll(rowsSelector);
}
var rows = new List<IElement>();
foreach (var rowDom in rowsDom)
{
rows.Add(rowDom);
}
// merge following rows for After selector
var after = search.Rows.After;
if (after > 0)
{
for (var i = 0; i < rows.Count; i += 1)
{
for (var i = 0; i < rows.Count; i += 1)
var currentRow = rows[i];
for (var j = 0; j < after; j += 1)
{
var currentRow = rows[i];
for (var j = 0; j < after; j += 1)
var mergeRowIndex = i + j + 1;
var mergeRow = rows[mergeRowIndex];
var mergeNodes = new List<INode>();
foreach (var node in mergeRow.ChildNodes)
{
var mergeRowIndex = i + j + 1;
var mergeRow = rows[mergeRowIndex];
var mergeNodes = new List<INode>();
foreach (var node in mergeRow.ChildNodes)
{
mergeNodes.Add(node);
}
currentRow.Append(mergeNodes.ToArray());
mergeNodes.Add(node);
}
rows.RemoveRange(i + 1, after);
currentRow.Append(mergeNodes.ToArray());
}
rows.RemoveRange(i + 1, after);
}
}
foreach (var row in rows)
foreach (var row in rows)
{
try
{
try
{
var release = new TorrentInfo();
var release = new TorrentInfo();
// Parse fields
foreach (var field in search.Fields)
// Parse fields
foreach (var field in search.Fields)
{
var fieldParts = field.Key.Split('|');
var fieldName = fieldParts[0];
var fieldModifiers = new List<string>();
for (var i = 1; i < fieldParts.Length; i++)
{
var fieldParts = field.Key.Split('|');
var fieldName = fieldParts[0];
var fieldModifiers = new List<string>();
for (var i = 1; i < fieldParts.Length; i++)
fieldModifiers.Add(fieldParts[i]);
}
string value = null;
var variablesKey = ".Result." + fieldName;
var isOptional = OptionalFields.Contains(field.Key) || fieldModifiers.Contains("optional") || field.Value.Optional;
try
{
value = HandleSelector(field.Value, row, variables, !isOptional);
if (isOptional && string.IsNullOrWhiteSpace(value))
{
fieldModifiers.Add(fieldParts[i]);
variables[variablesKey] = null;
continue;
}
string value = null;
var variablesKey = ".Result." + fieldName;
var isOptional = OptionalFields.Contains(field.Key) || fieldModifiers.Contains("optional") || field.Value.Optional;
variables[variablesKey] = ParseFields(value, fieldName, release, fieldModifiers, searchUrlUri);
}
catch (Exception ex)
{
if (!variables.ContainsKey(variablesKey))
{
variables[variablesKey] = null;
}
if (OptionalFields.Contains(field.Key) || fieldModifiers.Contains("optional") || field.Value.Optional)
{
variables[variablesKey] = null;
continue;
}
if (indexerLogging)
{
_logger.Trace("Error while parsing field={0}, selector={1}, value={2}: {3}", field.Key, field.Value.Selector, value == null ? "<null>" : value, ex.Message);
}
}
}
var filters = search.Rows.Filters;
var skipRelease = ParseRowFilters(filters, release, variables, row.ToHtmlPretty());
if (skipRelease)
{
continue;
}
// if DateHeaders is set go through the previous rows and look for the header selector
var dateHeaders = _definition.Search.Rows.Dateheaders;
if (release.PublishDate == DateTime.MinValue && dateHeaders != null)
{
var prevRow = row.PreviousElementSibling;
string value = null;
if (prevRow == null)
{
// continue with parent
var parent = row.ParentElement;
if (parent != null)
{
prevRow = parent.PreviousElementSibling;
}
}
while (prevRow != null)
{
var curRow = prevRow;
_logger.Debug(prevRow.OuterHtml);
try
{
value = HandleSelector(field.Value, row, variables, !isOptional);
if (isOptional && string.IsNullOrWhiteSpace(value))
{
variables[variablesKey] = null;
continue;
}
variables[variablesKey] = ParseFields(value, fieldName, release, fieldModifiers, searchUrlUri);
value = HandleSelector(dateHeaders, curRow);
break;
}
catch (Exception ex)
catch (Exception)
{
if (!variables.ContainsKey(variablesKey))
{
variables[variablesKey] = null;
}
if (OptionalFields.Contains(field.Key) || fieldModifiers.Contains("optional") || field.Value.Optional)
{
variables[variablesKey] = null;
continue;
}
if (indexerLogging)
{
_logger.Trace("Error while parsing field={0}, selector={1}, value={2}: {3}", field.Key, field.Value.Selector, value == null ? "<null>" : value, ex.Message);
}
// do nothing
}
}
var filters = search.Rows.Filters;
var skipRelease = ParseRowFilters(filters, release, variables, row.ToHtmlPretty());
if (skipRelease)
{
continue;
}
// if DateHeaders is set go through the previous rows and look for the header selector
var dateHeaders = _definition.Search.Rows.Dateheaders;
if (release.PublishDate == DateTime.MinValue && dateHeaders != null)
{
var prevRow = row.PreviousElementSibling;
string value = null;
prevRow = curRow.PreviousElementSibling;
if (prevRow == null)
{
// continue with parent
var parent = row.ParentElement;
var parent = curRow.ParentElement;
if (parent != null)
{
prevRow = parent.PreviousElementSibling;
}
}
while (prevRow != null)
{
var curRow = prevRow;
_logger.Debug(prevRow.OuterHtml);
try
{
value = HandleSelector(dateHeaders, curRow);
break;
}
catch (Exception)
{
// do nothing
}
prevRow = curRow.PreviousElementSibling;
if (prevRow == null)
{
// continue with parent
var parent = curRow.ParentElement;
if (parent != null)
{
prevRow = parent.PreviousElementSibling;
}
}
}
if (value == null && dateHeaders.Optional == false)
{
throw new CardigannException(string.Format("No date header row found for {0}", release.ToString()));
}
if (value != null)
{
release.PublishDate = DateTimeUtil.FromUnknown(value);
}
}
releases.Add(release);
}
catch (Exception ex)
{
_logger.Error(ex, "CardigannIndexer ({0}): Error while parsing row '{1}':\n\n{2}", _definition.Id, row.ToHtmlPretty());
if (value == null && dateHeaders.Optional == false)
{
throw new CardigannException(string.Format("No date header row found for {0}", release.ToString()));
}
if (value != null)
{
release.PublishDate = DateTimeUtil.FromUnknown(value);
}
}
releases.Add(release);
}
catch (Exception ex)
{
_logger.Error(ex, "CardigannIndexer ({0}): Error while parsing row '{1}':\n\n{2}", _definition.Id, row.ToHtmlPretty());
}
}
catch (Exception)
{
// OnParseError(results, ex);
throw;
}
}
/*
if (query.Limit > 0)
{
releases = releases.Take(query.Limit).ToList();
}*/
releases.ForEach(c =>
{
// generate magnet link from info hash (not allowed for private sites)
@@ -425,11 +411,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
break;
case "comments":
var commentsUrl = ResolvePath(value, searchUrlUri);
if (release.CommentUrl == null)
{
release.CommentUrl = commentsUrl.AbsoluteUri;
}
release.CommentUrl ??= commentsUrl.AbsoluteUri;
value = commentsUrl.ToString();
break;
case "title":
@@ -522,7 +504,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
break;
case "date":
release.PublishDate = DateTimeUtil.FromUnknown(value);
value = release.PublishDate.ToString(DateTimeUtil.Rfc1123ZPattern);
value = release.PublishDate.ToString(DateTimeUtil.Rfc1123ZPattern, CultureInfo.InvariantCulture);
break;
case "files":
release.Files = ParseUtil.CoerceInt(value);
@@ -554,38 +536,23 @@ namespace NzbDrone.Core.Indexers.Cardigann
value = release.ImdbId.ToString();
break;
case "tmdbid":
var tmdbIDRegEx = new Regex(@"(\d+)", RegexOptions.Compiled);
var tmdbIDMatch = tmdbIDRegEx.Match(value);
var tmdbID = tmdbIDMatch.Groups[1].Value;
release.TmdbId = (int)ParseUtil.CoerceLong(tmdbID);
release.TmdbId = (int)ParseUtil.GetLongFromString(value);
value = release.TmdbId.ToString();
break;
case "rageid":
var rageIDRegEx = new Regex(@"(\d+)", RegexOptions.Compiled);
var rageIDMatch = rageIDRegEx.Match(value);
var rageID = rageIDMatch.Groups[1].Value;
release.TvRageId = (int)ParseUtil.CoerceLong(rageID);
release.TvRageId = (int)ParseUtil.GetLongFromString(value);
value = release.TvRageId.ToString();
break;
case "traktid":
var traktIDRegEx = new Regex(@"(\d+)", RegexOptions.Compiled);
var traktIDMatch = traktIDRegEx.Match(value);
var traktID = traktIDMatch.Groups[1].Value;
release.TraktId = (int)ParseUtil.CoerceLong(traktID);
release.TraktId = (int)ParseUtil.GetLongFromString(value);
value = release.TraktId.ToString();
break;
case "tvdbid":
var tvdbIdRegEx = new Regex(@"(\d+)", RegexOptions.Compiled);
var tvdbIdMatch = tvdbIdRegEx.Match(value);
var tvdbId = tvdbIdMatch.Groups[1].Value;
release.TvdbId = (int)ParseUtil.CoerceLong(tvdbId);
release.TvdbId = (int)ParseUtil.GetLongFromString(value);
value = release.TvdbId.ToString();
break;
case "doubanid":
var doubanIDRegEx = new Regex(@"(\d+)", RegexOptions.Compiled);
var doubanIDMatch = doubanIDRegEx.Match(value);
var doubanID = doubanIDMatch.Groups[1].Value;
release.DoubanId = (int)ParseUtil.CoerceLong(doubanID);
release.DoubanId = (int)ParseUtil.GetLongFromString(value);
value = release.DoubanId.ToString();
break;
case "poster":
@@ -598,8 +565,12 @@ namespace NzbDrone.Core.Indexers.Cardigann
value = release.PosterUrl;
break;
case "genre":
release.Genres ??= new List<string>();
char[] delimiters = { ',', ' ', '/', ')', '(', '.', ';', '[', ']', '"', '|', ':' };
release.Genres = release.Genres.Union(value.Split(delimiters, System.StringSplitOptions.RemoveEmptyEntries)).ToList();
release.Genres = release.Genres
.Union(value.Split(delimiters, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries))
.Select(x => x.Replace("_", " "))
.ToList();
value = string.Join(", ", release.Genres);
break;
case "year":
@@ -645,29 +616,14 @@ namespace NzbDrone.Core.Indexers.Cardigann
switch (filter.Name)
{
case "andmatch":
var characterLimit = -1;
if (filter.Args != null)
{
characterLimit = int.Parse(filter.Args);
}
var queryKeywords = variables[".Keywords"] as string;
// See IndexerBase.FilterReleasesByQuery
break;
case "strdump":
// for debugging
_logger.Debug(string.Format("CardigannIndexer ({0}): row strdump: {1}", _definition.Id, row.ToString()));
break;
case "validate":
char[] delimiters = { ',', ' ', '/', ')', '(', '.', ';', '[', ']', '"', '|', ':' };
var args = (string)filter.Args;
var argsList = args.ToLower().Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
var validList = argsList.ToList();
var validIntersect = validList.Intersect(row.ToString().ToLower().Split(delimiters, StringSplitOptions.RemoveEmptyEntries)).ToList();
row = string.Join(", ", validIntersect);
_logger.Debug($"CardigannIndexer ({_definition.Id}): row strdump: {row}");
break;
default:
_logger.Error(string.Format("CardigannIndexer ({0}): Unsupported rows filter: {1}", _definition.Id, filter.Name));
_logger.Error($"CardigannIndexer ({_definition.Id}): Unsupported rows filter: {filter.Name}");
break;
}
}

View File

@@ -4,12 +4,12 @@ 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;
using AngleSharp.Html.Parser;
using Newtonsoft.Json.Linq;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Definitions.Cardigann;
@@ -29,22 +29,24 @@ namespace NzbDrone.Core.Indexers.Cardigann
protected IHtmlDocument landingResultDocument;
protected override string SiteLink => ResolveSiteLink();
private readonly TimeSpan _rateLimit;
public CardigannRequestGenerator(IConfigService configService,
CardigannDefinition definition,
Logger logger)
Logger logger,
TimeSpan rateLimit)
: base(configService, definition, logger)
{
_rateLimit = rateLimit;
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
_logger.Trace("Getting Movie search");
var pageableRequests = new IndexerPageableRequestChain();
var variables = GetQueryVariableDefaults(searchCriteria);
variables[".Query.Movie"] = null;
@@ -56,17 +58,13 @@ namespace NzbDrone.Core.Indexers.Cardigann
variables[".Query.TraktID"] = searchCriteria.TraktId?.ToString() ?? null;
variables[".Query.DoubanID"] = searchCriteria.DoubanId?.ToString() ?? null;
pageableRequests.Add(GetRequest(variables));
return pageableRequests;
return GetRequest(variables, searchCriteria);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
_logger.Trace("Getting Music search");
var pageableRequests = new IndexerPageableRequestChain();
var variables = GetQueryVariableDefaults(searchCriteria);
variables[".Query.Album"] = searchCriteria.Album;
@@ -76,17 +74,13 @@ namespace NzbDrone.Core.Indexers.Cardigann
variables[".Query.Year"] = searchCriteria.Year?.ToString() ?? null;
variables[".Query.Track"] = searchCriteria.Track;
pageableRequests.Add(GetRequest(variables));
return pageableRequests;
return GetRequest(variables, searchCriteria);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
_logger.Trace("Getting TV search");
var pageableRequests = new IndexerPageableRequestChain();
var variables = GetQueryVariableDefaults(searchCriteria);
variables[".Query.Series"] = null;
@@ -104,17 +98,13 @@ namespace NzbDrone.Core.Indexers.Cardigann
variables[".Query.DoubanID"] = searchCriteria.DoubanId?.ToString() ?? null;
variables[".Query.Episode"] = searchCriteria.EpisodeSearchString;
pageableRequests.Add(GetRequest(variables));
return pageableRequests;
return GetRequest(variables, searchCriteria);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
_logger.Trace("Getting Book search");
var pageableRequests = new IndexerPageableRequestChain();
var variables = GetQueryVariableDefaults(searchCriteria);
variables[".Query.Author"] = searchCriteria.Author;
@@ -123,22 +113,16 @@ namespace NzbDrone.Core.Indexers.Cardigann
variables[".Query.Publisher"] = searchCriteria.Publisher;
variables[".Query.Year"] = searchCriteria.Year?.ToString() ?? null;
pageableRequests.Add(GetRequest(variables));
return pageableRequests;
return GetRequest(variables, searchCriteria);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
_logger.Trace("Getting Basic search");
var pageableRequests = new IndexerPageableRequestChain();
var variables = GetQueryVariableDefaults(searchCriteria);
pageableRequests.Add(GetRequest(variables));
return pageableRequests;
return GetRequest(variables, searchCriteria);
}
private Dictionary<string, object> GetQueryVariableDefaults(SearchCriteriaBase searchCriteria)
@@ -148,8 +132,8 @@ namespace NzbDrone.Core.Indexers.Cardigann
variables[".Query.Type"] = searchCriteria.SearchType;
variables[".Query.Q"] = searchCriteria.SearchTerm;
variables[".Query.Categories"] = searchCriteria.Categories;
variables[".Query.Limit"] = searchCriteria.Limit?.ToString() ?? null;
variables[".Query.Offset"] = searchCriteria.Offset?.ToString() ?? null;
variables[".Query.Limit"] = searchCriteria.Limit.ToString() ?? null;
variables[".Query.Offset"] = searchCriteria.Offset.ToString() ?? null;
variables[".Query.Extended"] = null;
variables[".Query.APIKey"] = null;
variables[".Query.Genre"] = null;
@@ -190,6 +174,9 @@ namespace NzbDrone.Core.Indexers.Cardigann
{
var login = _definition.Login;
var variables = GetBaseTemplateVariables();
var headers = ParseCustomHeaders(_definition.Login?.Headers ?? _definition.Search?.Headers, variables);
if (login.Method == "post")
{
var pairs = new Dictionary<string, string>();
@@ -218,9 +205,20 @@ namespace NzbDrone.Core.Indexers.Cardigann
requestBuilder.AddFormParameter(pair.Key, pair.Value);
}
requestBuilder.Headers.Add("Referer", SiteLink);
Cookies = null;
if (login.Cookies != null)
{
Cookies = CookieUtil.CookieHeaderToDictionary(string.Join("; ", login.Cookies));
}
var response = await HttpClient.ExecuteProxiedAsync(requestBuilder.Build(), Definition);
var request = requestBuilder
.SetCookies(Cookies ?? new Dictionary<string, string>())
.SetHeaders(headers ?? new Dictionary<string, string>())
.SetHeader("Referer", SiteLink)
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
var response = await HttpClient.ExecuteProxiedAsync(request, Definition);
Cookies = response.GetCookies();
@@ -235,13 +233,9 @@ namespace NzbDrone.Core.Indexers.Cardigann
var queryCollection = new NameValueCollection();
var pairs = new Dictionary<string, string>();
var formSelector = login.Form;
if (formSelector == null)
{
formSelector = "form";
}
var formSelector = login.Form ?? "form";
// landingResultDocument might not be initiated if the login is caused by a relogin during a query
// landingResultDocument might not be initiated if the login is caused by a re-login during a query
if (landingResultDocument == null)
{
await GetConfigurationForSetup(true);
@@ -273,11 +267,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
continue;
}
var value = input.GetAttribute("value");
if (value == null)
{
value = "";
}
var value = input.GetAttribute("value") ?? "";
pairs[name] = value;
}
@@ -356,11 +346,14 @@ namespace NzbDrone.Core.Indexers.Cardigann
Encoding = _encoding
};
requestBuilder.SetCookies(Cookies);
var request = requestBuilder
.SetCookies(Cookies)
.SetHeaders(headers ?? new Dictionary<string, string>())
.SetHeader("Referer", loginUrl)
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
requestBuilder.Headers.Add("Referer", loginUrl);
var simpleCaptchaResult = await HttpClient.ExecuteProxiedAsync(requestBuilder.Build(), Definition);
var simpleCaptchaResult = await HttpClient.ExecuteProxiedAsync(request, Definition);
var simpleCaptchaJSON = JObject.Parse(simpleCaptchaResult.Content);
var captchaSelection = simpleCaptchaJSON["images"][0]["hash"].ToString();
@@ -398,7 +391,6 @@ namespace NzbDrone.Core.Indexers.Cardigann
var enctype = form.GetAttribute("enctype");
if (enctype == "multipart/form-data")
{
var headers = new Dictionary<string, string>();
var boundary = "---------------------------" + DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds.ToString().Replace(".", "");
var bodyParts = new List<string>();
@@ -424,21 +416,18 @@ namespace NzbDrone.Core.Indexers.Cardigann
Encoding = _encoding
};
requestBuilder.Headers.Add("Referer", SiteLink);
requestBuilder.SetCookies(Cookies);
foreach (var pair in pairs)
{
requestBuilder.AddFormParameter(pair.Key, pair.Value);
}
foreach (var header in headers)
{
requestBuilder.SetHeader(header.Key, header.Value);
}
var request = requestBuilder
.SetCookies(Cookies)
.SetHeaders(headers ?? new Dictionary<string, string>())
.SetHeader("Referer", SiteLink)
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
var request = requestBuilder.Build();
request.SetContent(body);
loginResult = await HttpClient.ExecuteProxiedAsync(request, Definition);
@@ -454,15 +443,19 @@ namespace NzbDrone.Core.Indexers.Cardigann
Encoding = _encoding
};
requestBuilder.SetCookies(Cookies);
requestBuilder.Headers.Add("Referer", loginUrl);
foreach (var pair in pairs)
{
requestBuilder.AddFormParameter(pair.Key, pair.Value);
}
loginResult = await HttpClient.ExecuteProxiedAsync(requestBuilder.Build(), Definition);
var request = requestBuilder
.SetCookies(Cookies)
.SetHeaders(headers ?? new Dictionary<string, string>())
.SetHeader("Referer", loginUrl)
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
loginResult = await HttpClient.ExecuteProxiedAsync(request, Definition);
}
Cookies = loginResult.GetCookies();
@@ -496,9 +489,13 @@ namespace NzbDrone.Core.Indexers.Cardigann
Encoding = _encoding
};
requestBuilder.Headers.Add("Referer", SiteLink);
var request = requestBuilder
.SetHeaders(headers ?? new Dictionary<string, string>())
.SetHeader("Referer", SiteLink)
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
var response = await HttpClient.ExecuteProxiedAsync(requestBuilder.Build(), Definition);
var response = await HttpClient.ExecuteProxiedAsync(request, Definition);
Cookies = response.GetCookies();
@@ -521,9 +518,13 @@ namespace NzbDrone.Core.Indexers.Cardigann
Encoding = _encoding
};
requestBuilder.Headers.Add("Referer", SiteLink);
var request = requestBuilder
.SetHeaders(headers ?? new Dictionary<string, string>())
.SetHeader("Referer", SiteLink)
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
var response = await HttpClient.ExecuteProxiedAsync(requestBuilder.Build(), Definition);
var response = await HttpClient.ExecuteProxiedAsync(request, Definition);
Cookies = response.GetCookies();
@@ -533,7 +534,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
}
else
{
throw new NotImplementedException("Login method " + login.Method + " not implemented");
throw new NotImplementedException($"Login method {login.Method} not implemented");
}
}
@@ -578,15 +579,11 @@ namespace NzbDrone.Core.Indexers.Cardigann
return null;
}
var variables = GetBaseTemplateVariables();
var headers = ParseCustomHeaders(_definition.Login?.Headers ?? _definition.Search?.Headers, variables);
var loginUrl = ResolvePath(login.Path);
Cookies = null;
if (login.Cookies != null)
{
Cookies = CookieUtil.CookieHeaderToDictionary(string.Join("; ", login.Cookies));
}
var requestBuilder = new HttpRequestBuilder(loginUrl.AbsoluteUri)
{
LogResponseContent = true,
@@ -594,14 +591,18 @@ namespace NzbDrone.Core.Indexers.Cardigann
Encoding = _encoding
};
requestBuilder.Headers.Add("Referer", SiteLink);
if (Cookies != null)
Cookies = null;
if (login.Cookies != null)
{
requestBuilder.SetCookies(Cookies);
Cookies = CookieUtil.CookieHeaderToDictionary(string.Join("; ", login.Cookies));
}
var request = requestBuilder.Build();
var request = requestBuilder
.SetCookies(Cookies ?? new Dictionary<string, string>())
.SetHeaders(headers ?? new Dictionary<string, string>())
.SetHeader("Referer", SiteLink)
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
landingResult = await HttpClient.ExecuteProxiedAsync(request, Definition);
@@ -634,6 +635,9 @@ namespace NzbDrone.Core.Indexers.Cardigann
{
var captcha = login.Captcha;
var variables = GetBaseTemplateVariables();
var headers = ParseCustomHeaders(_definition.Login?.Headers ?? _definition.Search?.Headers, variables);
if (captcha.Type == "image")
{
var captchaElement = landingResultDocument.QuerySelector(captcha.Selector);
@@ -644,8 +648,10 @@ namespace NzbDrone.Core.Indexers.Cardigann
var request = new HttpRequestBuilder(captchaUrl.ToString())
.SetCookies(landingResult.GetCookies())
.SetHeaders(headers ?? new Dictionary<string, string>())
.SetHeader("Referer", loginUrl.AbsoluteUri)
.SetEncoding(_encoding)
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
var response = await HttpClient.ExecuteProxiedAsync(request, Definition);
@@ -656,10 +662,8 @@ namespace NzbDrone.Core.Indexers.Cardigann
ImageData = response.ResponseData
};
}
else
{
_logger.Debug("CardigannIndexer ({0}): No captcha image found", _definition.Id);
}
_logger.Debug("CardigannIndexer ({0}): No captcha image found", _definition.Id);
}
else
{
@@ -689,8 +693,6 @@ namespace NzbDrone.Core.Indexers.Cardigann
{
var requestLinkStr = ResolvePath(ApplyGoTemplateText(request.Path, variables)).ToString();
_logger.Debug("CardigannIndexer ({0}): handleRequest() requestLinkStr= {1}", _definition.Id, requestLinkStr);
Dictionary<string, string> pairs = null;
var queryCollection = new NameValueCollection();
@@ -724,25 +726,36 @@ namespace NzbDrone.Core.Indexers.Cardigann
requestLinkStr += queryCollection.GetQueryString(_encoding, separator: request.Queryseparator);
}
var httpRequest = new HttpRequestBuilder(requestLinkStr)
.SetCookies(Cookies ?? new Dictionary<string, string>())
.SetEncoding(_encoding)
.SetHeader("Referer", referer);
httpRequest.Method = method;
var httpRequestBuilder = new HttpRequestBuilder(requestLinkStr)
{
Method = method,
Encoding = _encoding
};
// Add form data for POST requests
if (method == HttpMethod.Post)
{
foreach (var param in pairs)
{
httpRequest.AddFormParameter(param.Key, param.Value);
httpRequestBuilder.AddFormParameter(param.Key, param.Value);
}
}
var response = await HttpClient.ExecuteProxiedAsync(httpRequest.Build(), Definition);
var headers = ParseCustomHeaders(_definition.Download?.Headers ?? _definition.Search?.Headers, variables);
var httpRequest = httpRequestBuilder
.SetCookies(Cookies ?? new Dictionary<string, string>())
.SetHeaders(headers ?? new Dictionary<string, string>())
.SetHeader("Referer", referer)
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
_logger.Debug("CardigannIndexer ({0}): handleRequest() httpRequest={1}", _definition.Id, httpRequest);
var response = await HttpClient.ExecuteProxiedAsync(httpRequest, Definition);
_logger.Debug("CardigannIndexer ({0}): handleRequest() remote server returned {1}", _definition.Id, response.StatusCode);
return response;
}
@@ -750,11 +763,10 @@ namespace NzbDrone.Core.Indexers.Cardigann
{
Cookies = GetCookies();
var method = HttpMethod.Get;
var headers = new Dictionary<string, string>();
var variables = GetBaseTemplateVariables();
AddTemplateVariablesFromUri(variables, link, ".DownloadUri");
headers = ParseCustomHeaders(_definition.Search?.Headers, variables);
var headers = ParseCustomHeaders(_definition.Download?.Headers ?? _definition.Search?.Headers, variables);
if (_definition.Download != null)
{
@@ -766,6 +778,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
.SetCookies(Cookies ?? new Dictionary<string, string>())
.SetHeaders(headers ?? new Dictionary<string, string>())
.SetEncoding(_encoding)
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
request.AllowAutoRedirect = true;
@@ -791,7 +804,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
{
try
{
if (!download.Infohash.UseBeforeResponse || download.Before == null || response == null)
if (!download.Infohash.Usebeforeresponse || download.Before == null || response == null)
{
response = await HttpClient.ExecuteProxiedAsync(request, Definition);
}
@@ -799,13 +812,13 @@ namespace NzbDrone.Core.Indexers.Cardigann
var hash = MatchSelector(response, download.Infohash.Hash, variables);
if (hash == null)
{
throw new CardigannException($"InfoHash selectors didn't match");
throw new CardigannException("InfoHash selectors didn't match hash.");
}
var title = MatchSelector(response, download.Infohash.Title, variables);
if (title == null)
{
throw new CardigannException($"InfoHash selectors didn't match");
throw new CardigannException("InfoHash selectors didn't match title.");
}
var magnet = MagnetLinkBuilder.BuildPublicMagnetLink(hash, title);
@@ -837,7 +850,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
try
{
if (!selector.UseBeforeResponse || download.Before == null || response == null)
if (!selector.Usebeforeresponse || download.Before == null || response == null)
{
response = await HttpClient.ExecuteProxiedAsync(request, Definition);
}
@@ -856,6 +869,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
.SetCookies(Cookies ?? new Dictionary<string, string>())
.SetHeaders(headers ?? new Dictionary<string, string>())
.SetEncoding(_encoding)
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
response = await HttpClient.ExecuteProxiedAsync(testLinkRequest, Definition);
@@ -875,6 +889,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
.SetCookies(Cookies ?? new Dictionary<string, string>())
.SetHeaders(headers ?? new Dictionary<string, string>())
.SetEncoding(_encoding)
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
selectorDownloadRequest.Method = method;
@@ -895,6 +910,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
.SetCookies(Cookies ?? new Dictionary<string, string>())
.SetHeaders(headers ?? new Dictionary<string, string>())
.SetEncoding(_encoding)
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
downloadRequest.Method = method;
@@ -907,8 +923,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
var selectorText = ApplyGoTemplateText(selector.Selector, variables);
var parser = new HtmlParser();
var results = response.Content;
var resultDocument = parser.ParseDocument(results);
var resultDocument = parser.ParseDocument(response.Content);
var element = resultDocument.QuerySelector(selectorText);
if (element == null)
@@ -981,7 +996,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
return false;
}
private IEnumerable<IndexerRequest> GetRequest(Dictionary<string, object> variables)
private IEnumerable<IndexerRequest> GetRequest(Dictionary<string, object> variables, SearchCriteriaBase searchCriteria)
{
var search = _definition.Search;
@@ -1012,115 +1027,154 @@ namespace NzbDrone.Core.Indexers.Cardigann
variables[".Query.Keywords"] = string.Join(" ", keywordTokens);
variables[".Keywords"] = ApplyFilters((string)variables[".Query.Keywords"], search.Keywordsfilters, variables);
var pageSize = search.PageSize;
var minPage = 0;
var maxPage = 0;
if (pageSize > 0)
{
variables[".PageSize"] = pageSize;
minPage = (searchCriteria.Offset / pageSize) + search.FirstPageNumber;
maxPage = ((searchCriteria.Offset + searchCriteria.Limit - 1) / pageSize) + search.FirstPageNumber;
}
if (pageSize == 0 && searchCriteria.Offset >= 100)
{
// Indexer doesn't support pagination
yield break;
}
// TODO: prepare queries first and then send them parallel
var searchPaths = search.Paths;
foreach (var searchPath in searchPaths)
// Grab all pages we will need to return user requested limit and offset
for (var page = minPage; page <= maxPage; page++)
{
// skip path if categories don't match
if (searchPath.Categories != null && mappedCategories.Count > 0)
variables[".Query.Page"] = page;
foreach (var searchPath in searchPaths)
{
var invertMatch = searchPath.Categories[0] == "!";
var hasIntersect = mappedCategories.Intersect(searchPath.Categories).Any();
if (invertMatch)
// skip path if categories don't match
if (searchPath.Categories != null && mappedCategories.Count > 0)
{
hasIntersect = !hasIntersect;
}
if (!hasIntersect)
{
continue;
}
}
// build search URL
// 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;
if (string.Equals(searchPath.Method, "post", StringComparison.OrdinalIgnoreCase))
{
method = HttpMethod.Post;
}
var inputsList = new List<Dictionary<string, string>>();
if (searchPath.Inheritinputs)
{
inputsList.Add(search.Inputs);
}
inputsList.Add(searchPath.Inputs);
foreach (var inputs in inputsList)
{
if (inputs != null)
{
foreach (var input in inputs)
var invertMatch = searchPath.Categories[0] == "!";
var hasIntersect = mappedCategories.Intersect(searchPath.Categories).Any();
if (invertMatch)
{
if (input.Key == "$raw")
hasIntersect = !hasIntersect;
}
if (!hasIntersect)
{
continue;
}
}
// build search URL
// 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;
if (string.Equals(searchPath.Method, "post", StringComparison.OrdinalIgnoreCase))
{
method = HttpMethod.Post;
}
var inputsList = new List<Dictionary<string, string>>();
if (searchPath.Inheritinputs)
{
inputsList.Add(search.Inputs);
}
inputsList.Add(searchPath.Inputs);
foreach (var inputs in inputsList)
{
if (inputs != null)
{
foreach (var input in inputs)
{
var rawStr = ApplyGoTemplateText(input.Value, variables, WebUtility.UrlEncode);
foreach (var part in rawStr.Split('&'))
if (input.Key == "$raw")
{
var parts = part.Split(new char[] { '=' }, 2);
var key = parts[0];
if (key.Length == 0)
var rawStr = ApplyGoTemplateText(input.Value, variables, WebUtility.UrlEncode);
foreach (var part in rawStr.Split('&'))
{
continue;
}
var parts = part.Split(new char[] { '=' }, 2);
var key = parts[0];
if (key.Length == 0)
{
continue;
}
var value = "";
if (parts.Length == 2)
{
value = parts[1];
}
var value = "";
if (parts.Length == 2)
{
value = parts[1];
}
queryCollection.Add(key, value);
queryCollection.Add(key, value);
}
}
else
{
var inputValue = ApplyGoTemplateText(input.Value, variables);
if (inputValue.IsNotNullOrWhiteSpace() || search.AllowEmptyInputs)
{
queryCollection.Add(input.Key, inputValue);
}
}
}
else
{
queryCollection.Add(input.Key, ApplyGoTemplateText(input.Value, variables));
}
}
}
}
if (method == HttpMethod.Get)
{
if (queryCollection.Count > 0)
if (method == HttpMethod.Get)
{
searchUrl += "?" + queryCollection.GetQueryString(_encoding);
if (queryCollection.Count > 0)
{
searchUrl += "?" + queryCollection.GetQueryString(_encoding);
}
}
}
_logger.Info($"Adding request: {searchUrl}");
_logger.Info($"Adding request: {searchUrl}");
var requestbuilder = new HttpRequestBuilder(searchUrl);
requestbuilder.Method = method;
// Add FormData for searchs that POST
if (method == HttpMethod.Post)
{
foreach (var param in queryCollection)
var requestBuilder = new HttpRequestBuilder(searchUrl)
{
requestbuilder.AddFormParameter(param.Key, param.Value);
Method = method,
Encoding = _encoding
};
// Add FormData for searchs that POST
if (method == HttpMethod.Post)
{
foreach (var param in queryCollection)
{
requestBuilder.AddFormParameter(param.Key, param.Value);
}
}
// send HTTP request
if (search.Headers != null)
{
var headers = ParseCustomHeaders(search.Headers, variables);
requestBuilder.SetHeaders(headers ?? new Dictionary<string, string>());
}
var request = requestBuilder
.WithRateLimit(_rateLimit.TotalSeconds)
.Build();
var cardigannRequest = new CardigannRequest(request, variables, searchPath)
{
HttpRequest =
{
AllowAutoRedirect = searchPath.Followredirect
}
};
yield return cardigannRequest;
}
// send HTTP request
if (search.Headers != null)
{
var headers = ParseCustomHeaders(search.Headers, variables);
requestbuilder.SetHeaders(headers ?? new Dictionary<string, string>());
}
var request = new CardigannRequest(requestbuilder.SetEncoding(_encoding).Build(), variables, searchPath);
request.HttpRequest.AllowAutoRedirect = searchPath.Followredirect;
yield return request;
}
}
}

View File

@@ -16,9 +16,8 @@ public class FileListRequestGenerator : IIndexerRequestGenerator
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
if (searchCriteria.ImdbId.IsNotNullOrWhiteSpace() || searchCriteria.SearchTerm.IsNotNullOrWhiteSpace())
@@ -47,14 +46,11 @@ public class FileListRequestGenerator : IIndexerRequestGenerator
}
}
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
if (searchCriteria.ImdbId.IsNotNullOrWhiteSpace())
@@ -70,14 +66,11 @@ public class FileListRequestGenerator : IIndexerRequestGenerator
parameters.Set("query", searchCriteria.SanitizedSearchTerm.Trim());
}
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
if (searchCriteria.SearchTerm.IsNotNullOrWhiteSpace())
@@ -87,14 +80,11 @@ public class FileListRequestGenerator : IIndexerRequestGenerator
parameters.Set("query", searchCriteria.SanitizedSearchTerm.Trim());
}
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
if (searchCriteria.SearchTerm.IsNotNullOrWhiteSpace())
@@ -104,14 +94,11 @@ public class FileListRequestGenerator : IIndexerRequestGenerator
parameters.Set("query", searchCriteria.SanitizedSearchTerm.Trim());
}
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
if (searchCriteria.SearchTerm.IsNotNullOrWhiteSpace())
@@ -121,9 +108,7 @@ public class FileListRequestGenerator : IIndexerRequestGenerator
parameters.Set("query", searchCriteria.SanitizedSearchTerm.Trim());
}
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
private IEnumerable<IndexerRequest> GetPagedRequests(SearchCriteriaBase searchCriteria, NameValueCollection parameters)

View File

@@ -137,49 +137,29 @@ public class FunFileRequestGenerator : IIndexerRequestGenerator
_capabilities = capabilities;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}", searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}", searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
@@ -288,11 +268,11 @@ public class FunFileParser : IParseIndexerResponse
throw new Exception("Download links not found. Make sure you can download from the website.");
}
var link = _settings.BaseUrl + qDownloadLink.GetAttribute("href");
var downloadUrl = _settings.BaseUrl + qDownloadLink.GetAttribute("href");
var qDetailsLink = row.QuerySelector("a[href^=\"details.php?id=\"]");
var title = qDetailsLink?.GetAttribute("title")?.Trim();
var details = _settings.BaseUrl + qDetailsLink?.GetAttribute("href")?.Replace("&hit=1", "");
var infoUrl = _settings.BaseUrl + qDetailsLink?.GetAttribute("href")?.Replace("&hit=1", "");
var categoryLink = row.QuerySelector("a[href^=\"browse.php?cat=\"]")?.GetAttribute("href");
var cat = ParseUtil.GetArgumentFromQueryString(categoryLink, "cat");
@@ -302,9 +282,9 @@ public class FunFileParser : IParseIndexerResponse
var release = new TorrentInfo
{
Guid = link,
InfoUrl = link,
DownloadUrl = details,
Guid = infoUrl,
InfoUrl = infoUrl,
DownloadUrl = downloadUrl,
Title = title,
Categories = _categories.MapTrackerCatToNewznab(cat),
Size = ParseUtil.GetBytes(row.Children[7].TextContent),

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
@@ -106,8 +107,23 @@ public abstract class GazelleBase<TSettings> : TorrentIndexerBase<TSettings>
return response;
}
protected override IDictionary<string, string> GetCookies()
{
if (Settings is GazelleUserPassOrCookieSettings cookieSettings && !string.IsNullOrWhiteSpace(cookieSettings.Cookie))
{
return CookieUtil.CookieHeaderToDictionary(cookieSettings.Cookie);
}
return base.GetCookies();
}
protected override bool CheckIfLoginNeeded(HttpResponse response)
{
if (Settings is GazelleUserPassOrCookieSettings cookieSettings && !string.IsNullOrWhiteSpace(cookieSettings.Cookie))
{
return false;
}
var invalidResponses = new[] { "\"bad credentials\"", "\"groupName\":\"wrong-creds\"" };
return response.HasHttpRedirect || (response.Content != null && invalidResponses.Any(response.Content.Contains));

View File

@@ -42,10 +42,8 @@ public class GazelleRequestGenerator : IIndexerRequestGenerator
yield return request;
}
public virtual IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public virtual IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories);
if (searchCriteria.ImdbId != null)
@@ -53,15 +51,11 @@ public class GazelleRequestGenerator : IIndexerRequestGenerator
parameters.Set(ImdbInTags ? "taglist" : "cataloguenumber", searchCriteria.FullImdbId);
}
pageableRequests.Add(GetRequest(parameters));
return pageableRequests;
return GetRequest(parameters);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories);
if (searchCriteria.Artist.IsNotNullOrWhiteSpace() && searchCriteria.Artist != "VA")
@@ -79,15 +73,11 @@ public class GazelleRequestGenerator : IIndexerRequestGenerator
parameters.Set("recordlabel", searchCriteria.Label);
}
pageableRequests.Add(GetRequest(parameters));
return pageableRequests;
return GetRequest(parameters);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = GetBasicSearchParameters(searchCriteria.SanitizedTvSearchString, searchCriteria.Categories);
if (searchCriteria.ImdbId != null)
@@ -95,29 +85,21 @@ public class GazelleRequestGenerator : IIndexerRequestGenerator
parameters.Set(ImdbInTags ? "taglist" : "cataloguenumber", searchCriteria.FullImdbId);
}
pageableRequests.Add(GetRequest(parameters));
return pageableRequests;
return GetRequest(parameters);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories);
pageableRequests.Add(GetRequest(parameters));
return pageableRequests;
return GetRequest(parameters);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories);
pageableRequests.Add(GetRequest(parameters));
return pageableRequests;
return GetRequest(parameters);
}
// hook to adjust the search term

View File

@@ -4,13 +4,14 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions.Gazelle;
public class GazelleSettingsValidator : UserPassBaseSettingsValidator<GazelleSettings>
public class GazelleSettingsValidator<T> : UserPassBaseSettingsValidator<T>
where T : GazelleSettings
{
}
public class GazelleSettings : UserPassTorrentBaseSettings
{
private static readonly GazelleSettingsValidator Validator = new ();
private static readonly GazelleSettingsValidator<GazelleSettings> Validator = new ();
public string AuthKey { get; set; }
public string PassKey { get; set; }

View File

@@ -0,0 +1,31 @@
using FluentValidation;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions.Gazelle;
public class GazelleUserPassOrCookieValidator<T> : NoAuthSettingsValidator<T>
where T : GazelleUserPassOrCookieSettings
{
public GazelleUserPassOrCookieValidator()
{
RuleFor(c => c.Username).NotEmpty().When(c => c.Cookie.IsNullOrWhiteSpace());
RuleFor(c => c.Password).NotEmpty().When(c => c.Cookie.IsNullOrWhiteSpace());
RuleFor(c => c.Cookie).NotEmpty().When(c => c.Username.IsNullOrWhiteSpace() && c.Password.IsNullOrWhiteSpace());
}
}
public class GazelleUserPassOrCookieSettings : GazelleSettings
{
private static readonly GazelleUserPassOrCookieValidator<GazelleUserPassOrCookieSettings> Validator = new ();
[FieldDefinition(4, Label = "Cookie", HelpText = "Use the Cookie field only if 2FA is enabled for your account, leave it empty otherwise.", Privacy = PrivacyLevel.Password)]
public string Cookie { get; set; }
public override NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}

View File

@@ -203,49 +203,29 @@ namespace NzbDrone.Core.Indexers.Definitions
{
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories)));
return pageableRequests;
return GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories)));
return pageableRequests;
return GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories)));
return pageableRequests;
return GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories)));
return pageableRequests;
return GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories)));
return pageableRequests;
return GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
}
public void FetchPasskey()

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
@@ -15,6 +15,7 @@ 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;
@@ -74,7 +75,7 @@ public class GreatPosterWallRequestGenerator : GazelleRequestGenerator
_settings = settings;
}
public override IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public override IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var parameters = GetBasicSearchParameters(searchCriteria.SearchTerm, searchCriteria.Categories);
@@ -83,9 +84,7 @@ public class GreatPosterWallRequestGenerator : GazelleRequestGenerator
parameters.Set("searchstr", searchCriteria.FullImdbId);
}
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(parameters));
return pageableRequests;
return GetRequest(parameters);
}
protected override NameValueCollection GetBasicSearchParameters(string term, int[] categories)
@@ -118,17 +117,23 @@ public class GreatPosterWallParser : GazelleParser
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
{
// Remove cookie cache
CookiesUpdater(null, null);
if (indexerResponse.HttpResponse.HasHttpRedirect)
{
if (indexerResponse.HttpResponse.RedirectUrl.ContainsIgnoreCase("login.php"))
{
// Remove cookie cache
CookiesUpdater(null, null);
throw new IndexerException(indexerResponse, "We are being redirected to the login page. Most likely your session expired or was killed. Recheck your cookie or credentials and try testing the indexer.");
}
throw new IndexerException(indexerResponse, $"Redirected to {indexerResponse.HttpResponse.RedirectUrl} from API request");
}
throw new IndexerException(indexerResponse, $"Unexpected response status {indexerResponse.HttpResponse.StatusCode} code from API request");
}
if (!indexerResponse.HttpResponse.Headers.ContentType.Contains(HttpAccept.Json.Value))
{
// Remove cookie cache
CookiesUpdater(null, null);
throw new IndexerException(indexerResponse, $"Unexpected response header {indexerResponse.HttpResponse.Headers.ContentType} from API request, expected {HttpAccept.Json.Value}");
}
@@ -231,10 +236,17 @@ public class GreatPosterWallParser : GazelleParser
}
}
public class GreatPosterWallSettings : GazelleSettings
public class GreatPosterWallSettings : GazelleUserPassOrCookieSettings
{
private static readonly GazelleUserPassOrCookieValidator<GreatPosterWallSettings> Validator = new ();
[FieldDefinition(6, Label = "Freeleech Only", Type = FieldType.Checkbox, HelpText = "Search freeleech torrents only")]
public bool FreeleechOnly { get; set; }
public override NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
public class GreatPosterWallResponse

View File

@@ -16,9 +16,8 @@ namespace NzbDrone.Core.Indexers.Definitions.HDBits
public IndexerCapabilities Capabilities { get; set; }
public HDBitsSettings Settings { get; set; }
public virtual IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public virtual IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var query = new TorrentQuery();
var imdbId = ParseUtil.GetImdbID(searchCriteria.ImdbId).GetValueOrDefault(0);
@@ -38,9 +37,7 @@ namespace NzbDrone.Core.Indexers.Definitions.HDBits
query.ImdbInfo.Id = imdbId;
}
pageableRequests.Add(GetRequest(query));
return pageableRequests;
return GetRequest(query);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
@@ -68,14 +65,13 @@ namespace NzbDrone.Core.Indexers.Definitions.HDBits
yield return new IndexerRequest(request);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var query = new TorrentQuery();
var tvdbId = searchCriteria.TvdbId.GetValueOrDefault(0);
var imdbId = ParseUtil.GetImdbID(searchCriteria.ImdbId).GetValueOrDefault(0);
@@ -112,19 +108,16 @@ namespace NzbDrone.Core.Indexers.Definitions.HDBits
query.ImdbInfo.Id = imdbId;
}
pageableRequests.Add(GetRequest(query));
return pageableRequests;
return GetRequest(query);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var query = new TorrentQuery();
if (searchCriteria.Categories?.Length > 0)
@@ -137,9 +130,7 @@ namespace NzbDrone.Core.Indexers.Definitions.HDBits
query.Search = searchCriteria.SanitizedSearchTerm;
}
pageableRequests.Add(GetRequest(query));
return pageableRequests;
return GetRequest(query);
}
}
}

View File

@@ -178,45 +178,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.ImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.ImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.ImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.ImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -166,49 +166,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -25,18 +25,15 @@ namespace NzbDrone.Core.Indexers.Headphones
PageSize = 100;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
return pageableRequests;
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var capabilities = Capabilities;
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
if (searchCriteria.Artist.IsNotNullOrWhiteSpace() && capabilities.MusicSearchArtistAvailable)
@@ -67,30 +64,22 @@ namespace NzbDrone.Core.Indexers.Headphones
}
}
pageableRequests.Add(GetPagedRequests(searchCriteria,
parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
return pageableRequests;
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
return pageableRequests;
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var capabilities = Capabilities;
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
@@ -99,9 +88,7 @@ namespace NzbDrone.Core.Indexers.Headphones
parameters.Add("q", NewsnabifyTitle(searchCriteria.SearchTerm));
}
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
private IEnumerable<IndexerRequest> GetPagedRequests(SearchCriteriaBase searchCriteria, NameValueCollection parameters)
@@ -120,15 +107,9 @@ namespace NzbDrone.Core.Indexers.Headphones
baseUrl += "&apikey=" + Settings.ApiKey;
}
if (searchCriteria.Limit.HasValue)
{
parameters.Add("limit", searchCriteria.Limit.ToString());
}
parameters.Add("limit", searchCriteria.Limit.ToString());
if (searchCriteria.Offset.HasValue)
{
parameters.Add("offset", searchCriteria.Offset.ToString());
}
parameters.Add("offset", searchCriteria.Offset.ToString());
var request = new IndexerRequest(string.Format("{0}&{1}", baseUrl, parameters.GetQueryString()), HttpAccept.Rss);
request.HttpRequest.Credentials = new BasicNetworkCredential(Settings.Username, Settings.Password);

View File

@@ -212,49 +212,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories, searchCriteria.Limit ?? 100, searchCriteria.Offset ?? 0, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories, searchCriteria.Limit, searchCriteria.Offset, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit ?? 100, searchCriteria.Offset ?? 0));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit, searchCriteria.Offset);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.Limit ?? 100, searchCriteria.Offset ?? 0, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.Limit, searchCriteria.Offset, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit ?? 100, searchCriteria.Offset ?? 0));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit, searchCriteria.Offset);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit ?? 100, searchCriteria.Offset ?? 0));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit, searchCriteria.Offset);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -166,49 +166,29 @@ namespace NzbDrone.Core.Indexers.Definitions
_capabilities = capabilities;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories)

View File

@@ -123,9 +123,8 @@ public class LibbleRequestGenerator : IIndexerRequestGenerator
_capabilities = capabilities;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
if (searchCriteria.Artist.IsNotNullOrWhiteSpace() && searchCriteria.Artist != "VA")
@@ -157,34 +156,29 @@ public class LibbleRequestGenerator : IIndexerRequestGenerator
parameters.Set("tags_type", "0");
}
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
private IEnumerable<IndexerRequest> GetPagedRequests(SearchCriteriaBase searchCriteria, NameValueCollection parameters)
@@ -206,7 +200,7 @@ public class LibbleRequestGenerator : IIndexerRequestGenerator
queryCats.ForEach(cat => parameters.Set($"filter_cat[{cat}]", "1"));
}
if (searchCriteria.Offset.HasValue && searchCriteria.Limit.HasValue && searchCriteria.Offset > 0 && searchCriteria.Limit > 0)
if (searchCriteria.Offset > 0 && searchCriteria.Limit > 0)
{
var page = (int)(searchCriteria.Offset / searchCriteria.Limit) + 1;
parameters.Set("page", page.ToString());

View File

@@ -90,28 +90,26 @@ public class MoreThanTVRequestGenerator : IIndexerRequestGenerator
};
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
=> PerformRequest(searchCriteria);
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
=> PerformRequest(searchCriteria);
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
=> PerformRequest(searchCriteria);
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
=> PerformRequest(searchCriteria);
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> 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)
private IEnumerable<IndexerRequest> 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)
@@ -127,9 +125,7 @@ public class MoreThanTVRequestGenerator : IIndexerRequestGenerator
}
}
chain.Add(requests);
return chain;
return requests;
}
private string GetTorrentSearchUrl(SearchCriteriaBase query, string overrideSearchTerm = null)

View File

@@ -236,8 +236,8 @@ namespace NzbDrone.Core.Indexers.Definitions
{ "tor[srchIn][narrator]", "true" },
{ "tor[searchIn]", "torrents" },
{ "tor[sortType]", "default" },
{ "tor[perpage]", searchCriteria.Limit?.ToString() ?? "100" },
{ "tor[startNumber]", searchCriteria.Offset?.ToString() ?? "0" },
{ "tor[perpage]", searchCriteria.Limit.ToString() },
{ "tor[startNumber]", searchCriteria.Offset.ToString() },
{ "thumbnails", "1" }, // gives links for thumbnail sized versions of their posters
{ "description", "1" } // include the description
};
@@ -284,37 +284,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(searchCriteria));
return pageableRequests;
return GetPagedRequests(searchCriteria);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(searchCriteria));
return pageableRequests;
return GetPagedRequests(searchCriteria);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -46,12 +46,17 @@ namespace NzbDrone.Core.Indexers.Definitions
return new NebulanceParser(Settings);
}
public override async Task<byte[]> Download(Uri link)
protected override Task<HttpRequest> GetDownloadRequest(Uri link)
{
// Invalidate cookies before downloading to prevent redirect to login page.
UpdateCookies(null, null);
// Avoid using cookies to prevent redirects to login page
var requestBuilder = new HttpRequestBuilder(link.AbsoluteUri)
{
AllowAutoRedirect = FollowRedirect
};
return await base.Download(link);
var request = requestBuilder.Build();
return Task.FromResult(request);
}
private IndexerCapabilities SetCapabilities()
@@ -93,20 +98,18 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return new IndexerRequest(builder.Build());
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var queryParams = new NebulanceQuery
{
Age = ">0"
@@ -136,20 +139,16 @@ namespace NzbDrone.Core.Indexers.Definitions
}
}
pageableRequests.Add(GetPagedRequests(queryParams, searchCriteria.Limit, searchCriteria.Offset));
return pageableRequests;
return GetPagedRequests(queryParams, searchCriteria.Limit, searchCriteria.Offset);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var queryParams = new NebulanceQuery
{
Age = ">0"
@@ -160,9 +159,7 @@ namespace NzbDrone.Core.Indexers.Definitions
queryParams.Name = "%" + Regex.Replace(searchCriteria.SanitizedSearchTerm, @"[ -._]+", "%").Trim() + "%";
}
pageableRequests.Add(GetPagedRequests(queryParams, searchCriteria.Limit, searchCriteria.Offset));
return pageableRequests;
return GetPagedRequests(queryParams, searchCriteria.Limit, searchCriteria.Offset);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -26,11 +26,10 @@ namespace NzbDrone.Core.Indexers.Newznab
PageSize = 100;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var capabilities = _capabilitiesProvider.GetCapabilities(Settings, Definition);
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
if (searchCriteria.TmdbId.HasValue && capabilities.MovieSearchTmdbAvailable)
@@ -66,18 +65,13 @@ namespace NzbDrone.Core.Indexers.Newznab
}
}
pageableRequests.Add(GetPagedRequests(searchCriteria,
capabilities,
parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, capabilities, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var capabilities = _capabilitiesProvider.GetCapabilities(Settings, Definition);
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
if (searchCriteria.Artist.IsNotNullOrWhiteSpace() && capabilities.MusicSearchArtistAvailable)
@@ -108,18 +102,13 @@ namespace NzbDrone.Core.Indexers.Newznab
}
}
pageableRequests.Add(GetPagedRequests(searchCriteria,
capabilities,
parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, capabilities, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var capabilities = _capabilitiesProvider.GetCapabilities(Settings, Definition);
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
if (searchCriteria.TvdbId.HasValue && capabilities.TvSearchTvdbAvailable)
@@ -175,18 +164,13 @@ namespace NzbDrone.Core.Indexers.Newznab
}
}
pageableRequests.Add(GetPagedRequests(searchCriteria,
capabilities,
parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, capabilities, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var capabilities = _capabilitiesProvider.GetCapabilities(Settings, Definition);
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
if (searchCriteria.Author.IsNotNullOrWhiteSpace() && capabilities.BookSearchAuthorAvailable)
@@ -217,17 +201,12 @@ namespace NzbDrone.Core.Indexers.Newznab
}
}
pageableRequests.Add(GetPagedRequests(searchCriteria,
capabilities,
parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, capabilities, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var capabilities = _capabilitiesProvider.GetCapabilities(Settings, Definition);
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
@@ -236,9 +215,7 @@ namespace NzbDrone.Core.Indexers.Newznab
parameters.Set("q", NewsnabifyTitle(searchCriteria.SearchTerm));
}
pageableRequests.Add(GetPagedRequests(searchCriteria, capabilities, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, capabilities, parameters);
}
private IEnumerable<IndexerRequest> GetPagedRequests(SearchCriteriaBase searchCriteria, IndexerCapabilities capabilities, NameValueCollection parameters)
@@ -262,15 +239,9 @@ namespace NzbDrone.Core.Indexers.Newznab
searchUrl += "&apikey=" + Settings.ApiKey;
}
if (searchCriteria.Limit.HasValue)
{
parameters.Set("limit", searchCriteria.Limit.ToString());
}
parameters.Set("limit", searchCriteria.Limit.ToString());
if (searchCriteria.Offset.HasValue)
{
parameters.Set("offset", searchCriteria.Offset.ToString());
}
parameters.Set("offset", searchCriteria.Offset.ToString());
if (parameters.Count > 0)
{

View File

@@ -199,49 +199,29 @@ public class NorBitsRequestGenerator : IIndexerRequestGenerator
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}", searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}", searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -1054,49 +1054,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit ?? 100, searchCriteria.Offset ?? 0));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit, searchCriteria.Offset);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit ?? 100, searchCriteria.Offset ?? 0));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit, searchCriteria.Offset);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.Limit ?? 100, searchCriteria.Offset ?? 0));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.Limit, searchCriteria.Offset);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit ?? 100, searchCriteria.Offset ?? 0));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit, searchCriteria.Offset);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit ?? 100, searchCriteria.Offset ?? 0));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.Limit, searchCriteria.Offset);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -112,7 +112,7 @@ namespace NzbDrone.Core.Indexers.Definitions
_logger.Error("Download failed");
}
ValidateTorrent(downloadBytes);
ValidateDownloadData(downloadBytes);
return downloadBytes;
}
@@ -132,9 +132,8 @@ namespace NzbDrone.Core.Indexers.Definitions
_capabilities = capabilities;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
if (searchCriteria.Artist.IsNotNullOrWhiteSpace() && searchCriteria.Artist != "VA")
@@ -152,39 +151,31 @@ namespace NzbDrone.Core.Indexers.Definitions
parameters.Set("year", searchCriteria.Year.ToString());
}
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
private IEnumerable<IndexerRequest> GetPagedRequests(SearchCriteriaBase searchCriteria, NameValueCollection parameters)

View File

@@ -18,20 +18,14 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
public IIndexerHttpClient HttpClient { get; set; }
public Logger Logger { get; set; }
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
if (searchCriteria.ImdbId.IsNotNullOrWhiteSpace())
{
pageableRequests.Add(GetRequest(searchCriteria.FullImdbId));
}
else
{
pageableRequests.Add(GetRequest(string.Format("{0}", searchCriteria.SearchTerm)));
return GetRequest(searchCriteria.FullImdbId);
}
return pageableRequests;
return GetRequest(string.Format("{0}", searchCriteria.SearchTerm));
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
@@ -72,28 +66,24 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(string.Format("{0}", searchCriteria.SearchTerm)));
return pageableRequests;
return GetRequest(string.Format("{0}", searchCriteria.SearchTerm));
}
}
}

View File

@@ -135,37 +135,29 @@ public class PirateTheNetRequestGenerator : IIndexerRequestGenerator
_capabilities = capabilities;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)

View File

@@ -269,49 +269,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -276,49 +276,29 @@ public class PreToMeRequestGenerator : IIndexerRequestGenerator
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}", searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedTvSearchString}", searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests($"{searchCriteria.SanitizedSearchTerm}", searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using NLog;
@@ -9,11 +10,12 @@ using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Exceptions;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Rarbg
namespace NzbDrone.Core.Indexers.Definitions.Rarbg
{
public class Rarbg : TorrentIndexerBase<RarbgSettings>
{
@@ -24,7 +26,7 @@ namespace NzbDrone.Core.Indexers.Rarbg
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Public;
public override IndexerCapabilities Capabilities => SetCapabilities();
public override TimeSpan RateLimit => TimeSpan.FromSeconds(5);
public override TimeSpan RateLimit => TimeSpan.FromSeconds(7);
private readonly IRarbgTokenProvider _tokenProvider;
public Rarbg(IRarbgTokenProvider tokenProvider, IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
@@ -35,7 +37,7 @@ namespace NzbDrone.Core.Indexers.Rarbg
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new RarbgRequestGenerator(_tokenProvider) { Settings = Settings, Categories = Capabilities.Categories };
return new RarbgRequestGenerator(_tokenProvider, RateLimit) { Settings = Settings, Categories = Capabilities.Categories };
}
public override IParseIndexerResponse GetParser()
@@ -43,6 +45,23 @@ namespace NzbDrone.Core.Indexers.Rarbg
return new RarbgParser(Capabilities, _logger);
}
public static void CheckResponseByStatusCode(IndexerResponse response)
{
var responseCode = (int)response.HttpResponse.StatusCode;
switch (responseCode)
{
case (int)HttpStatusCode.TooManyRequests:
throw new TooManyRequestsException(response.HttpRequest, response.HttpResponse, TimeSpan.FromMinutes(2));
case 520:
throw new TooManyRequestsException(response.HttpRequest, response.HttpResponse, TimeSpan.FromMinutes(3));
case (int)HttpStatusCode.OK:
break;
default:
throw new IndexerException(response, "Indexer API call returned an unexpected StatusCode [{0}]", responseCode);
}
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
@@ -61,7 +80,7 @@ namespace NzbDrone.Core.Indexers.Rarbg
}
};
caps.Categories.AddCategoryMapping(4, NewznabStandardCategory.XXX, "XXX (18+)");
// caps.Categories.AddCategoryMapping(4, NewznabStandardCategory.XXX, "XXX (18+)"); // 3x is not supported by API #11848
caps.Categories.AddCategoryMapping(14, NewznabStandardCategory.MoviesSD, "Movies/XVID");
caps.Categories.AddCategoryMapping(17, NewznabStandardCategory.MoviesSD, "Movies/x264");
caps.Categories.AddCategoryMapping(18, NewznabStandardCategory.TVSD, "TV Episodes");
@@ -97,6 +116,8 @@ namespace NzbDrone.Core.Indexers.Rarbg
{
var response = await FetchIndexerResponse(request);
CheckResponseByStatusCode(response);
// try and recover from token errors
var jsonResponse = new HttpResponse<RarbgResponse>(response.HttpResponse);
@@ -106,7 +127,7 @@ namespace NzbDrone.Core.Indexers.Rarbg
{
_logger.Debug("Invalid or expired token, refreshing token from Rarbg");
_tokenProvider.ExpireToken(Settings);
var newToken = _tokenProvider.GetToken(Settings);
var newToken = _tokenProvider.GetToken(Settings, RateLimit);
var qs = HttpUtility.ParseQueryString(request.HttpRequest.Url.Query);
qs.Set("token", newToken);
@@ -151,7 +172,7 @@ namespace NzbDrone.Core.Indexers.Rarbg
Settings.Validate().Filter("BaseUrl").ThrowOnError();
var request = new HttpRequestBuilder(Settings.BaseUrl.Trim('/'))
.Resource($"/pubapi_v2.php?get_token=get_token&app_id={BuildInfo.AppName}")
.Resource($"/pubapi_v2.php?get_token=get_token&app_id=rralworP_{BuildInfo.Version}")
.Accept(HttpAccept.Json)
.Build();

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Text.RegularExpressions;
using NLog;
using NzbDrone.Common.EnvironmentInfo;
@@ -8,7 +7,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Indexers.Rarbg
namespace NzbDrone.Core.Indexers.Definitions.Rarbg
{
public class RarbgParser : IParseIndexerResponse
{
@@ -28,19 +27,8 @@ namespace NzbDrone.Core.Indexers.Rarbg
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var results = new List<ReleaseInfo>();
var responseCode = (int)indexerResponse.HttpResponse.StatusCode;
switch (responseCode)
{
case (int)HttpStatusCode.TooManyRequests:
throw new TooManyRequestsException(indexerResponse.HttpRequest, indexerResponse.HttpResponse, TimeSpan.FromMinutes(2));
case 520:
throw new TooManyRequestsException(indexerResponse.HttpRequest, indexerResponse.HttpResponse, TimeSpan.FromMinutes(3));
case (int)HttpStatusCode.OK:
break;
default:
throw new IndexerException(indexerResponse, "Indexer API call returned an unexpected StatusCode [{0}]", responseCode);
}
Rarbg.CheckResponseByStatusCode(indexerResponse);
var jsonResponse = new HttpResponse<RarbgResponse>(indexerResponse.HttpResponse);
@@ -84,7 +72,7 @@ namespace NzbDrone.Core.Indexers.Rarbg
Title = torrent.title,
Size = torrent.size,
DownloadUrl = torrent.download,
InfoUrl = $"{torrent.info_page}&app_id={BuildInfo.AppName}",
InfoUrl = $"{torrent.info_page}&app_id=rralworP_{BuildInfo.Version}",
PublishDate = torrent.pubdate.ToUniversalTime(),
Seeders = torrent.seeders,
Peers = torrent.leechers + torrent.seeders,

View File

@@ -6,43 +6,59 @@ using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.IndexerSearch.Definitions;
namespace NzbDrone.Core.Indexers.Rarbg
namespace NzbDrone.Core.Indexers.Definitions.Rarbg
{
public class RarbgRequestGenerator : IIndexerRequestGenerator
{
private readonly IRarbgTokenProvider _tokenProvider;
private readonly TimeSpan _rateLimit;
public RarbgSettings Settings { get; set; }
public IndexerCapabilitiesCategories Categories { get; set; }
public RarbgRequestGenerator(IRarbgTokenProvider tokenProvider)
public RarbgRequestGenerator(IRarbgTokenProvider tokenProvider, TimeSpan rateLimit)
{
_tokenProvider = tokenProvider;
_rateLimit = rateLimit;
}
private IEnumerable<IndexerRequest> GetRequest(string term, int[] categories, string imdbId = null, int? tmdbId = null, int? tvdbId = null)
private IEnumerable<IndexerRequest> GetRequest(bool isRssSearch, string term, int[] categories, string imdbId = null, int? tmdbId = null, int? tvdbId = null)
{
var requestBuilder = new HttpRequestBuilder(Settings.BaseUrl.Trim('/'))
.Resource("/pubapi_v2.php")
.AddQueryParam("mode", "search")
.AddQueryParam("limit", "100")
.AddQueryParam("token", _tokenProvider.GetToken(Settings, _rateLimit))
.AddQueryParam("format", "json_extended")
.AddQueryParam("app_id", $"rralworP_{BuildInfo.Version}")
.Accept(HttpAccept.Json);
if (imdbId.IsNotNullOrWhiteSpace())
if (isRssSearch)
{
requestBuilder.AddQueryParam("search_imdb", imdbId);
requestBuilder
.AddQueryParam("mode", "list")
.WithRateLimit(31);
}
else if (tmdbId.HasValue && tmdbId > 0)
else
{
requestBuilder.AddQueryParam("search_themoviedb", tmdbId);
}
else if (tvdbId.HasValue && tvdbId > 0)
{
requestBuilder.AddQueryParam("search_tvdb", tvdbId);
}
requestBuilder.AddQueryParam("mode", "search");
if (term.IsNotNullOrWhiteSpace())
{
requestBuilder.AddQueryParam("search_string", $"{term}");
if (imdbId.IsNotNullOrWhiteSpace())
{
requestBuilder.AddQueryParam("search_imdb", imdbId);
}
else if (tmdbId.HasValue && tmdbId > 0)
{
requestBuilder.AddQueryParam("search_themoviedb", tmdbId);
}
else if (tvdbId.HasValue && tvdbId > 0)
{
requestBuilder.AddQueryParam("search_tvdb", tvdbId);
}
if (term.IsNotNullOrWhiteSpace())
{
requestBuilder.AddQueryParam("search_string", $"{term}");
}
}
if (!Settings.RankedOnly)
@@ -51,55 +67,40 @@ namespace NzbDrone.Core.Indexers.Rarbg
}
var cats = Categories.MapTorznabCapsToTrackers(categories);
if (cats != null && cats.Count > 0)
if (cats == null || !cats.Any())
{
var categoryParam = string.Join(";", cats.Distinct());
requestBuilder.AddQueryParam("category", categoryParam);
// default to all, without specifying it some categories are missing (e.g. games), see #4146
cats = Categories.GetTrackerCategories();
}
requestBuilder.AddQueryParam("limit", "100");
requestBuilder.AddQueryParam("token", _tokenProvider.GetToken(Settings));
requestBuilder.AddQueryParam("format", "json_extended");
requestBuilder.AddQueryParam("app_id", BuildInfo.AppName);
requestBuilder.AddQueryParam("category", string.Join(";", cats.Distinct()));
yield return new IndexerRequest(requestBuilder.Build());
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories, searchCriteria.FullImdbId, searchCriteria.TmdbId));
return pageableRequests;
return GetRequest(searchCriteria.IsRssSearch, searchCriteria.SanitizedSearchTerm, searchCriteria.Categories, searchCriteria.FullImdbId, searchCriteria.TmdbId);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
return pageableRequests;
return GetRequest(searchCriteria.IsRssSearch, searchCriteria.SanitizedSearchTerm, searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(searchCriteria.SanitizedTvSearchString, searchCriteria.Categories, searchCriteria.FullImdbId, tvdbId: searchCriteria.TvdbId));
return pageableRequests;
return GetRequest(searchCriteria.IsRssSearch, searchCriteria.SanitizedTvSearchString, searchCriteria.Categories, searchCriteria.FullImdbId, tvdbId: searchCriteria.TvdbId);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
return pageableRequests;
return GetRequest(searchCriteria.IsRssSearch, searchCriteria.SanitizedSearchTerm, searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
return pageableRequests;
return GetRequest(searchCriteria.IsRssSearch, searchCriteria.SanitizedSearchTerm, searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace NzbDrone.Core.Indexers.Rarbg
namespace NzbDrone.Core.Indexers.Definitions.Rarbg
{
public class RarbgResponse
{

View File

@@ -1,7 +1,7 @@
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Indexers.Settings;
namespace NzbDrone.Core.Indexers.Rarbg
namespace NzbDrone.Core.Indexers.Definitions.Rarbg
{
public class RarbgSettings : NoAuthTorrentBaseSettings
{

View File

@@ -5,11 +5,11 @@ using NzbDrone.Common.Cache;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Http;
namespace NzbDrone.Core.Indexers.Rarbg
namespace NzbDrone.Core.Indexers.Definitions.Rarbg
{
public interface IRarbgTokenProvider
{
string GetToken(RarbgSettings settings);
string GetToken(RarbgSettings settings, TimeSpan rateLimit);
void ExpireToken(RarbgSettings settings);
}
@@ -31,16 +31,18 @@ namespace NzbDrone.Core.Indexers.Rarbg
_tokenCache.Remove(settings.BaseUrl);
}
public string GetToken(RarbgSettings settings)
public string GetToken(RarbgSettings settings, TimeSpan rateLimit)
{
return _tokenCache.Get(settings.BaseUrl,
() =>
{
var requestBuilder = new HttpRequestBuilder(settings.BaseUrl.Trim('/'))
.WithRateLimit(5.0)
.Resource($"/pubapi_v2.php?get_token=get_token&app_id={BuildInfo.AppName}")
.WithRateLimit(rateLimit.TotalSeconds)
.Resource($"/pubapi_v2.php?get_token=get_token&app_id=rralworP_{BuildInfo.Version}")
.Accept(HttpAccept.Json);
requestBuilder.LogResponseContent = true;
var response = _httpClient.Get<JObject>(requestBuilder.Build());
return response.Resource["token"].ToString();

View File

@@ -50,6 +50,20 @@ namespace NzbDrone.Core.Indexers.Definitions
return new RedactedParser(Settings, Capabilities.Categories);
}
protected override Task<HttpRequest> GetDownloadRequest(Uri link)
{
var requestBuilder = new HttpRequestBuilder(link.AbsoluteUri)
{
AllowAutoRedirect = FollowRedirect
};
var request = requestBuilder
.SetHeader("Authorization", Settings.Apikey)
.Build();
return Task.FromResult(request);
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
@@ -74,30 +88,6 @@ namespace NzbDrone.Core.Indexers.Definitions
return caps;
}
public override async Task<byte[]> Download(Uri link)
{
var request = new HttpRequestBuilder(link.AbsoluteUri)
.SetHeader("Authorization", Settings.Apikey)
.Build();
var downloadBytes = Array.Empty<byte>();
try
{
var response = await _httpClient.ExecuteProxiedAsync(request, Definition);
downloadBytes = response.ResponseData;
}
catch (Exception)
{
_indexerStatusService.RecordFailure(Definition.Id);
_logger.Error("Download failed");
}
ValidateTorrent(downloadBytes);
return downloadBytes;
}
}
public class RedactedRequestGenerator : IIndexerRequestGenerator
@@ -114,9 +104,8 @@ namespace NzbDrone.Core.Indexers.Definitions
_capabilities = capabilities;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
if (searchCriteria.Artist.IsNotNullOrWhiteSpace() && searchCriteria.Artist != "VA")
@@ -134,39 +123,31 @@ namespace NzbDrone.Core.Indexers.Definitions
parameters.Set("year", searchCriteria.Year.ToString());
}
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
return new List<IndexerRequest>();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new NameValueCollection();
pageableRequests.Add(GetPagedRequests(searchCriteria, parameters));
return pageableRequests;
return GetPagedRequests(searchCriteria, parameters);
}
private IEnumerable<IndexerRequest> GetPagedRequests(SearchCriteriaBase searchCriteria, NameValueCollection parameters)
@@ -188,18 +169,12 @@ namespace NzbDrone.Core.Indexers.Definitions
queryCats.ForEach(cat => parameters.Set($"filter_cat[{cat}]", "1"));
}
var request = RequestBuilder()
.Resource($"/ajax.php?{parameters.GetQueryString()}")
.Build();
var searchUrl = _settings.BaseUrl.TrimEnd('/') + $"/ajax.php?{parameters.GetQueryString()}";
yield return new IndexerRequest(request);
}
var request = new IndexerRequest(searchUrl, HttpAccept.Json);
request.HttpRequest.Headers.Set("Authorization", _settings.Apikey);
private HttpRequestBuilder RequestBuilder()
{
return new HttpRequestBuilder($"{_settings.BaseUrl.TrimEnd('/')}")
.Accept(HttpAccept.Json)
.SetHeader("Authorization", _settings.Apikey);
yield return request;
}
}

View File

@@ -185,49 +185,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -1506,54 +1506,34 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
if (searchCriteria.Season == null)
{
searchCriteria.Season = 0;
}
pageableRequests.Add(GetPagedRequests(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

View File

@@ -120,49 +120,29 @@ namespace NzbDrone.Core.Indexers.Definitions
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId);
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
public IEnumerable<IndexerRequest> GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
return GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories);
}
public Func<IDictionary<string, string>> GetCookies { get; set; }

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