1
0
mirror of https://github.com/Radarr/Radarr.git synced 2024-11-09 04:22:30 +01:00

New: Add support for prioritizing indexers (#5000)

This commit is contained in:
nitsua 2020-09-12 02:25:32 -04:00 committed by GitHub
parent 4fafdcabb7
commit 9a46d5165c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 125 additions and 18 deletions

View File

@ -43,13 +43,14 @@ function EditIndexerModalContent(props) {
enableInteractiveSearch, enableInteractiveSearch,
supportsRss, supportsRss,
supportsSearch, supportsSearch,
fields fields,
priority
} = item; } = item;
return ( return (
<ModalContent onModalClose={onModalClose}> <ModalContent onModalClose={onModalClose}>
<ModalHeader> <ModalHeader>
{`${id ? 'Edit' : 'Add'} Indexer - ${implementationName}`} {`${id ? translate('EditIndexer') : translate('AddIndexer')} - ${implementationName}`}
</ModalHeader> </ModalHeader>
<ModalBody> <ModalBody>
@ -134,7 +135,22 @@ function EditIndexerModalContent(props) {
); );
}) })
} }
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}
>
<FormLabel>{translate('IndexerPriority')}</FormLabel>
<FormInputGroup
type={inputTypes.NUMBER}
name="priority"
helpText={translate('IndexerPriorityHelpText')}
min={1}
max={50}
{...priority}
onChange={onInputChange}
/>
</FormGroup>
</Form> </Form>
} }
</ModalBody> </ModalBody>

View File

@ -69,7 +69,9 @@ class Indexer extends Component {
enableAutomaticSearch, enableAutomaticSearch,
enableInteractiveSearch, enableInteractiveSearch,
supportsRss, supportsRss,
supportsSearch supportsSearch,
priority,
showPriority
} = this.props; } = this.props;
return ( return (
@ -103,24 +105,30 @@ class Indexer extends Component {
{ {
supportsSearch && enableAutomaticSearch && supportsSearch && enableAutomaticSearch &&
<Label kind={kinds.SUCCESS}> <Label kind={kinds.SUCCESS}>
Automatic Search {translate('AutomaticSearch')}
</Label> </Label>
} }
{ {
supportsSearch && enableInteractiveSearch && supportsSearch && enableInteractiveSearch &&
<Label kind={kinds.SUCCESS}> <Label kind={kinds.SUCCESS}>
Interactive Search {translate('InteractiveSearch')}
</Label> </Label>
} }
{
showPriority &&
<Label kind={kinds.DEFAULT}>
{translate('Priority')}: {priority}
</Label>
}
{ {
!enableRss && !enableAutomaticSearch && !enableInteractiveSearch && !enableRss && !enableAutomaticSearch && !enableInteractiveSearch &&
<Label <Label
kind={kinds.DISABLED} kind={kinds.DISABLED}
outline={true} outline={true}
> >
Disabled {translate('Disabled')}
</Label> </Label>
} }
</div> </div>
@ -155,7 +163,9 @@ Indexer.propTypes = {
supportsRss: PropTypes.bool.isRequired, supportsRss: PropTypes.bool.isRequired,
supportsSearch: PropTypes.bool.isRequired, supportsSearch: PropTypes.bool.isRequired,
onCloneIndexerPress: PropTypes.func.isRequired, onCloneIndexerPress: PropTypes.func.isRequired,
onConfirmDeleteIndexer: PropTypes.func.isRequired onConfirmDeleteIndexer: PropTypes.func.isRequired,
priority: PropTypes.number.isRequired,
showPriority: PropTypes.bool.isRequired
}; };
export default Indexer; export default Indexer;

View File

@ -64,6 +64,8 @@ class Indexers extends Component {
isEditIndexerModalOpen isEditIndexerModalOpen
} = this.state; } = this.state;
const showPriority = items.some((index) => index.priority !== 25);
return ( return (
<FieldSet legend={translate('Indexers')}> <FieldSet legend={translate('Indexers')}>
<PageSectionContent <PageSectionContent
@ -77,6 +79,7 @@ class Indexers extends Component {
<Indexer <Indexer
key={item.id} key={item.id}
{...item} {...item}
showPriority={showPriority}
onCloneIndexerPress={this.onCloneIndexerPress} onCloneIndexerPress={this.onCloneIndexerPress}
onConfirmDeleteIndexer={onConfirmDeleteIndexer} onConfirmDeleteIndexer={onConfirmDeleteIndexer}
/> />

View File

@ -18,6 +18,7 @@ protected override void MapToResource(IndexerResource resource, IndexerDefinitio
resource.SupportsRss = definition.SupportsRss; resource.SupportsRss = definition.SupportsRss;
resource.SupportsSearch = definition.SupportsSearch; resource.SupportsSearch = definition.SupportsSearch;
resource.Protocol = definition.Protocol; resource.Protocol = definition.Protocol;
resource.Priority = definition.Priority;
} }
protected override void MapToModel(IndexerDefinition definition, IndexerResource resource) protected override void MapToModel(IndexerDefinition definition, IndexerResource resource)
@ -27,6 +28,7 @@ protected override void MapToModel(IndexerDefinition definition, IndexerResource
definition.EnableRss = resource.EnableRss; definition.EnableRss = resource.EnableRss;
definition.EnableAutomaticSearch = resource.EnableSearch; definition.EnableAutomaticSearch = resource.EnableSearch;
definition.EnableInteractiveSearch = resource.EnableSearch; definition.EnableInteractiveSearch = resource.EnableSearch;
definition.Priority = resource.Priority;
} }
protected override void Validate(IndexerDefinition definition, bool includeWarnings) protected override void Validate(IndexerDefinition definition, bool includeWarnings)

View File

@ -9,5 +9,6 @@ public class IndexerResource : ProviderResource
public bool SupportsRss { get; set; } public bool SupportsRss { get; set; }
public bool SupportsSearch { get; set; } public bool SupportsSearch { get; set; }
public DownloadProtocol Protocol { get; set; } public DownloadProtocol Protocol { get; set; }
public int Priority { get; set; }
} }
} }

View File

@ -51,7 +51,7 @@ private void GivenPreferredSize(double? size)
.Returns(new QualityDefinition { PreferredSize = size }); .Returns(new QualityDefinition { PreferredSize = size });
} }
private RemoteMovie GivenRemoteMovie(QualityModel quality, int age = 0, long size = 0, DownloadProtocol downloadProtocol = DownloadProtocol.Usenet, int runtime = 150) private RemoteMovie GivenRemoteMovie(QualityModel quality, int age = 0, long size = 0, DownloadProtocol downloadProtocol = DownloadProtocol.Usenet, int runtime = 150, int indexerPriority = 25)
{ {
var remoteMovie = new RemoteMovie(); var remoteMovie = new RemoteMovie();
remoteMovie.ParsedMovieInfo = new ParsedMovieInfo(); remoteMovie.ParsedMovieInfo = new ParsedMovieInfo();
@ -73,6 +73,7 @@ private RemoteMovie GivenRemoteMovie(QualityModel quality, int age = 0, long siz
remoteMovie.Release.Size = size; remoteMovie.Release.Size = size;
remoteMovie.Release.DownloadProtocol = downloadProtocol; remoteMovie.Release.DownloadProtocol = downloadProtocol;
remoteMovie.Release.Title = "A Movie 1998"; remoteMovie.Release.Title = "A Movie 1998";
remoteMovie.Release.IndexerPriority = indexerPriority;
remoteMovie.CustomFormats = new List<CustomFormat>(); remoteMovie.CustomFormats = new List<CustomFormat>();
remoteMovie.CustomFormatScore = 0; remoteMovie.CustomFormatScore = 0;
@ -449,13 +450,11 @@ public void should_prefer_better_custom_format2()
[Test] [Test]
public void should_prefer_2_custom_formats() public void should_prefer_2_custom_formats()
{ {
var quality1 = new QualityModel(Quality.Bluray720p); var remoteMovie1 = GivenRemoteMovie(new QualityModel(Quality.Bluray720p));
var remoteMovie1 = GivenRemoteMovie(quality1);
remoteMovie1.CustomFormats.Add(_customFormat1); remoteMovie1.CustomFormats.Add(_customFormat1);
remoteMovie1.CustomFormatScore = remoteMovie1.Movie.Profile.CalculateCustomFormatScore(remoteMovie1.CustomFormats); remoteMovie1.CustomFormatScore = remoteMovie1.Movie.Profile.CalculateCustomFormatScore(remoteMovie1.CustomFormats);
var quality2 = new QualityModel(Quality.Bluray720p); var remoteMovie2 = GivenRemoteMovie(new QualityModel(Quality.Bluray720p));
var remoteMovie2 = GivenRemoteMovie(quality2);
remoteMovie2.CustomFormats.AddRange(new List<CustomFormat> { _customFormat1, _customFormat2 }); remoteMovie2.CustomFormats.AddRange(new List<CustomFormat> { _customFormat1, _customFormat2 });
remoteMovie2.CustomFormatScore = remoteMovie2.Movie.Profile.CalculateCustomFormatScore(remoteMovie2.CustomFormats); remoteMovie2.CustomFormatScore = remoteMovie2.Movie.Profile.CalculateCustomFormatScore(remoteMovie2.CustomFormats);
@ -555,5 +554,39 @@ public void should_prefer_score_over_real_when_download_propers_is_do_not_prefer
qualifiedReports.First().RemoteMovie.ParsedMovieInfo.Quality.Revision.Real.Should().Be(0); qualifiedReports.First().RemoteMovie.ParsedMovieInfo.Quality.Revision.Real.Should().Be(0);
qualifiedReports.First().RemoteMovie.CustomFormatScore.Should().Be(10); qualifiedReports.First().RemoteMovie.CustomFormatScore.Should().Be(10);
} }
[Test]
public void sort_download_decisions_based_on_indexer_priority()
{
var remoteMovie1 = GivenRemoteMovie(new QualityModel(Quality.WEBDL1080p), indexerPriority: 25);
var remoteMovie2 = GivenRemoteMovie(new QualityModel(Quality.WEBDL1080p), indexerPriority: 50);
var remoteMovie3 = GivenRemoteMovie(new QualityModel(Quality.WEBDL1080p), indexerPriority: 1);
var decisions = new List<DownloadDecision>();
decisions.AddRange(new[] { new DownloadDecision(remoteMovie1), new DownloadDecision(remoteMovie2), new DownloadDecision(remoteMovie3) });
var qualifiedReports = Subject.PrioritizeDecisionsForMovies(decisions);
qualifiedReports.First().RemoteMovie.Should().Be(remoteMovie3);
qualifiedReports.Skip(1).First().RemoteMovie.Should().Be(remoteMovie1);
qualifiedReports.Last().RemoteMovie.Should().Be(remoteMovie2);
}
[Test]
public void ensure_download_decisions_indexer_priority_is_not_perfered_over_quality()
{
var remoteMovie1 = GivenRemoteMovie(new QualityModel(Quality.HDTV720p), indexerPriority: 25);
var remoteMovie2 = GivenRemoteMovie(new QualityModel(Quality.WEBDL1080p), indexerPriority: 50);
var remoteMovie3 = GivenRemoteMovie(new QualityModel(Quality.SDTV), indexerPriority: 1);
var remoteMovie4 = GivenRemoteMovie(new QualityModel(Quality.WEBDL1080p), indexerPriority: 25);
var decisions = new List<DownloadDecision>();
decisions.AddRange(new[] { new DownloadDecision(remoteMovie1), new DownloadDecision(remoteMovie2), new DownloadDecision(remoteMovie3), new DownloadDecision(remoteMovie4) });
var qualifiedReports = Subject.PrioritizeDecisionsForMovies(decisions);
qualifiedReports.First().RemoteMovie.Should().Be(remoteMovie4);
qualifiedReports.Skip(1).First().RemoteMovie.Should().Be(remoteMovie2);
qualifiedReports.Skip(2).First().RemoteMovie.Should().Be(remoteMovie1);
qualifiedReports.Last().RemoteMovie.Should().Be(remoteMovie3);
}
} }
} }

View File

@ -0,0 +1,14 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(184)]
public class add_priority_to_indexers : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("Indexers").AddColumn("Priority").AsInt32().NotNullable().WithDefaultValue(25);
}
}
}

View File

@ -32,6 +32,7 @@ public int Compare(DownloadDecision x, DownloadDecision y)
CompareQuality, CompareQuality,
CompareCustomFormatScore, CompareCustomFormatScore,
CompareProtocol, CompareProtocol,
CompareIndexerPriority,
CompareIndexerFlags, CompareIndexerFlags,
ComparePeersIfTorrent, ComparePeersIfTorrent,
CompareAgeIfUsenet, CompareAgeIfUsenet,
@ -50,11 +51,22 @@ private int CompareBy<TSubject, TValue>(TSubject left, TSubject right, Func<TSub
return leftValue.CompareTo(rightValue); return leftValue.CompareTo(rightValue);
} }
private int CompareByReverse<TSubject, TValue>(TSubject left, TSubject right, Func<TSubject, TValue> funcValue)
where TValue : IComparable<TValue>
{
return CompareBy(left, right, funcValue) * -1;
}
private int CompareAll(params int[] comparers) private int CompareAll(params int[] comparers)
{ {
return comparers.Select(comparer => comparer).FirstOrDefault(result => result != 0); return comparers.Select(comparer => comparer).FirstOrDefault(result => result != 0);
} }
private int CompareIndexerPriority(DownloadDecision x, DownloadDecision y)
{
return CompareByReverse(x.RemoteMovie.Release, y.RemoteMovie.Release, release => release.IndexerPriority);
}
private int CompareQuality(DownloadDecision x, DownloadDecision y) private int CompareQuality(DownloadDecision x, DownloadDecision y)
{ {
if (_configService.DownloadPropersAndRepacks == ProperDownloadTypes.DoNotPrefer) if (_configService.DownloadPropersAndRepacks == ProperDownloadTypes.DoNotPrefer)

View File

@ -48,7 +48,7 @@ public ProcessedDecisions ProcessDecisions(List<DownloadDecision> decisions)
foreach (var report in prioritizedDecisions) foreach (var report in prioritizedDecisions)
{ {
var remoteEpisode = report.RemoteMovie; var remoteMovie = report.RemoteMovie;
var downloadProtocol = report.RemoteMovie.Release.DownloadProtocol; var downloadProtocol = report.RemoteMovie.Release.DownloadProtocol;
// Skip if already grabbed // Skip if already grabbed
@ -72,19 +72,20 @@ public ProcessedDecisions ProcessDecisions(List<DownloadDecision> decisions)
try try
{ {
_downloadService.DownloadReport(remoteEpisode); _logger.Trace("Grabbing from Indexer {0} at priority {1}.", remoteMovie.Release.Indexer, remoteMovie.Release.IndexerPriority);
_downloadService.DownloadReport(remoteMovie);
grabbed.Add(report); grabbed.Add(report);
} }
catch (ReleaseUnavailableException) catch (ReleaseUnavailableException)
{ {
_logger.Warn("Failed to download release from indexer, no longer available. " + remoteEpisode); _logger.Warn("Failed to download release from indexer, no longer available. " + remoteMovie);
rejected.Add(report); rejected.Add(report);
} }
catch (Exception ex) catch (Exception ex)
{ {
if (ex is DownloadClientUnavailableException || ex is DownloadClientAuthenticationException) if (ex is DownloadClientUnavailableException || ex is DownloadClientAuthenticationException)
{ {
_logger.Debug(ex, "Failed to send release to download client, storing until later. " + remoteEpisode); _logger.Debug(ex, "Failed to send release to download client, storing until later. " + remoteMovie);
PreparePending(pendingAddQueue, grabbed, pending, report, PendingReleaseReason.DownloadClientUnavailable); PreparePending(pendingAddQueue, grabbed, pending, report, PendingReleaseReason.DownloadClientUnavailable);
if (downloadProtocol == DownloadProtocol.Usenet) if (downloadProtocol == DownloadProtocol.Usenet)
@ -98,7 +99,7 @@ public ProcessedDecisions ProcessDecisions(List<DownloadDecision> decisions)
} }
else else
{ {
_logger.Warn(ex, "Couldn't add report to download queue. " + remoteEpisode); _logger.Warn(ex, "Couldn't add report to download queue. " + remoteMovie);
} }
} }
} }
@ -129,7 +130,7 @@ private bool IsMovieProcessed(List<DownloadDecision> decisions, DownloadDecision
private void PreparePending(List<Tuple<DownloadDecision, PendingReleaseReason>> queue, List<DownloadDecision> grabbed, List<DownloadDecision> pending, DownloadDecision report, PendingReleaseReason reason) private void PreparePending(List<Tuple<DownloadDecision, PendingReleaseReason>> queue, List<DownloadDecision> grabbed, List<DownloadDecision> pending, DownloadDecision report, PendingReleaseReason reason)
{ {
// If a release was already grabbed with matching episodes we should store it as a fallback // If a release was already grabbed with a matching movie we should store it as a fallback
// and filter it out the next time it is processed. // and filter it out the next time it is processed.
// If a higher quality release failed to add to the download client, but a lower quality release // If a higher quality release failed to add to the download client, but a lower quality release
// was sent to another client we still list it normally so it apparent that it'll grab next time. // was sent to another client we still list it normally so it apparent that it'll grab next time.

View File

@ -22,6 +22,7 @@ public abstract class IndexerBase<TSettings> : IIndexer
public abstract string Name { get; } public abstract string Name { get; }
public abstract DownloadProtocol Protocol { get; } public abstract DownloadProtocol Protocol { get; }
public int Priority { get; set; }
public abstract bool SupportsRss { get; } public abstract bool SupportsRss { get; }
public abstract bool SupportsSearch { get; } public abstract bool SupportsSearch { get; }
@ -77,6 +78,7 @@ protected virtual IList<ReleaseInfo> CleanupReleases(IEnumerable<ReleaseInfo> re
c.IndexerId = Definition.Id; c.IndexerId = Definition.Id;
c.Indexer = Definition.Name; c.Indexer = Definition.Name;
c.DownloadProtocol = Protocol; c.DownloadProtocol = Protocol;
c.IndexerPriority = ((IndexerDefinition)Definition).Priority;
}); });
return result; return result;

View File

@ -10,6 +10,7 @@ public class IndexerDefinition : ProviderDefinition
public DownloadProtocol Protocol { get; set; } public DownloadProtocol Protocol { get; set; }
public bool SupportsRss { get; set; } public bool SupportsRss { get; set; }
public bool SupportsSearch { get; set; } public bool SupportsSearch { get; set; }
public int Priority { get; set; } = 25;
public override bool Enable => EnableRss || EnableAutomaticSearch || EnableInteractiveSearch; public override bool Enable => EnableRss || EnableAutomaticSearch || EnableInteractiveSearch;

View File

@ -6,6 +6,7 @@
"AddExclusion": "Add Exclusion", "AddExclusion": "Add Exclusion",
"AddImportExclusionHelpText": "Prevent movie from being added to Radarr by lists", "AddImportExclusionHelpText": "Prevent movie from being added to Radarr by lists",
"AddingTag": "Adding tag", "AddingTag": "Adding tag",
"AddIndexer": "Add Indexer",
"AddList": "Add List", "AddList": "Add List",
"AddListExclusion": "Add List Exclusion", "AddListExclusion": "Add List Exclusion",
"AddMovies": "Add Movies", "AddMovies": "Add Movies",
@ -47,6 +48,7 @@
"Authentication": "Authentication", "Authentication": "Authentication",
"AuthenticationMethodHelpText": "Require Username and Password to access Radarr", "AuthenticationMethodHelpText": "Require Username and Password to access Radarr",
"Automatic": "Automatic", "Automatic": "Automatic",
"AutomaticSearch": "Automatic Search",
"AutoRedownloadFailedHelpText": "Automatically search for and attempt to download a different release", "AutoRedownloadFailedHelpText": "Automatically search for and attempt to download a different release",
"AutoUnmonitorPreviouslyDownloadedMoviesHelpText": "Movies deleted from disk are automatically unmonitored in Radarr", "AutoUnmonitorPreviouslyDownloadedMoviesHelpText": "Movies deleted from disk are automatically unmonitored in Radarr",
"AvailabilityDelay": "Availability Delay", "AvailabilityDelay": "Availability Delay",
@ -165,6 +167,7 @@
"DetailedProgressBarHelpText": "Show text on progess bar", "DetailedProgressBarHelpText": "Show text on progess bar",
"Details": "Details", "Details": "Details",
"DigitalRelease": "Digital Release", "DigitalRelease": "Digital Release",
"Disabled": "Disabled",
"Discover": "Discover", "Discover": "Discover",
"DiskSpace": "Disk Space", "DiskSpace": "Disk Space",
"Docker": "Docker", "Docker": "Docker",
@ -194,6 +197,7 @@
"DownloadWarningCheckDownloadClientForMoreDetails": "Download warning: check download client for more details", "DownloadWarningCheckDownloadClientForMoreDetails": "Download warning: check download client for more details",
"Edit": "Edit", "Edit": "Edit",
"Edition": "Edition", "Edition": "Edition",
"EditIndexer": "Edit Indexer",
"EditMovie": "Edit Movie", "EditMovie": "Edit Movie",
"EditPerson": "Edit Person", "EditPerson": "Edit Person",
"EditRemotePathMapping": "Edit Remote Path Mapping", "EditRemotePathMapping": "Edit Remote Path Mapping",
@ -317,6 +321,8 @@
"IncludeUnmonitored": "Include Unmonitored", "IncludeUnmonitored": "Include Unmonitored",
"Indexer": "Indexer", "Indexer": "Indexer",
"IndexerFlags": "Indexer Flags", "IndexerFlags": "Indexer Flags",
"IndexerPriority": "Indexer Priority",
"IndexerPriorityHelpText": "Indexer Priority from 1 (Highest) to 50 (Lowest). Default: 25.",
"IndexerRssHealthCheckNoAvailableIndexers": "All rss-capable indexers are temporarily unavailable due to recent indexer errors", "IndexerRssHealthCheckNoAvailableIndexers": "All rss-capable indexers are temporarily unavailable due to recent indexer errors",
"IndexerRssHealthCheckNoIndexers": "No indexers available with RSS sync enabled, Radarr will not grab new releases automatically", "IndexerRssHealthCheckNoIndexers": "No indexers available with RSS sync enabled, Radarr will not grab new releases automatically",
"Indexers": "Indexers", "Indexers": "Indexers",
@ -329,6 +335,7 @@
"IndexerStatusCheckSingleClientMessage": "Indexers unavailable due to failures: {0}", "IndexerStatusCheckSingleClientMessage": "Indexers unavailable due to failures: {0}",
"Info": "Info", "Info": "Info",
"InteractiveImport": "Interactive Import", "InteractiveImport": "Interactive Import",
"InteractiveSearch": "Interactive Search",
"Interval": "Interval", "Interval": "Interval",
"KeyboardShortcuts": "Keyboard Shortcuts", "KeyboardShortcuts": "Keyboard Shortcuts",
"Language": "Language", "Language": "Language",
@ -494,6 +501,7 @@
"PreferIndexerFlagsHelpText": "Prioritize releases with special flags", "PreferIndexerFlagsHelpText": "Prioritize releases with special flags",
"PreferredSize": "Preferred Size", "PreferredSize": "Preferred Size",
"PreviewRename": "Preview Rename", "PreviewRename": "Preview Rename",
"Priority": "Priority",
"PriorityHelpText": "Prioritize multiple Download Clients. Round-Robin is used for clients with the same priority.", "PriorityHelpText": "Prioritize multiple Download Clients. Round-Robin is used for clients with the same priority.",
"Profiles": "Profiles", "Profiles": "Profiles",
"ProfilesSettingsSummary": "Quality, Language and Delay profiles", "ProfilesSettingsSummary": "Quality, Language and Delay profiles",

View File

@ -14,6 +14,7 @@ public class ReleaseInfo
public string CommentUrl { get; set; } public string CommentUrl { get; set; }
public int IndexerId { get; set; } public int IndexerId { get; set; }
public string Indexer { get; set; } public string Indexer { get; set; }
public int IndexerPriority { get; set; }
public DownloadProtocol DownloadProtocol { get; set; } public DownloadProtocol DownloadProtocol { get; set; }
public int TvdbId { get; set; } public int TvdbId { get; set; }
public int TvRageId { get; set; } public int TvRageId { get; set; }

View File

@ -10,6 +10,7 @@ public class IndexerResource : ProviderResource
public bool SupportsRss { get; set; } public bool SupportsRss { get; set; }
public bool SupportsSearch { get; set; } public bool SupportsSearch { get; set; }
public DownloadProtocol Protocol { get; set; } public DownloadProtocol Protocol { get; set; }
public int Priority { get; set; }
} }
public class IndexerResourceMapper : ProviderResourceMapper<IndexerResource, IndexerDefinition> public class IndexerResourceMapper : ProviderResourceMapper<IndexerResource, IndexerDefinition>
@ -29,6 +30,7 @@ public override IndexerResource ToResource(IndexerDefinition definition)
resource.SupportsRss = definition.SupportsRss; resource.SupportsRss = definition.SupportsRss;
resource.SupportsSearch = definition.SupportsSearch; resource.SupportsSearch = definition.SupportsSearch;
resource.Protocol = definition.Protocol; resource.Protocol = definition.Protocol;
resource.Priority = definition.Priority;
return resource; return resource;
} }
@ -45,6 +47,7 @@ public override IndexerDefinition ToModel(IndexerResource resource)
definition.EnableRss = resource.EnableRss; definition.EnableRss = resource.EnableRss;
definition.EnableAutomaticSearch = resource.EnableAutomaticSearch; definition.EnableAutomaticSearch = resource.EnableAutomaticSearch;
definition.EnableInteractiveSearch = resource.EnableInteractiveSearch; definition.EnableInteractiveSearch = resource.EnableInteractiveSearch;
definition.Priority = resource.Priority;
return definition; return definition;
} }