mirror of
https://github.com/Radarr/Radarr.git
synced 2025-04-24 14:37:07 -04:00
New: Per download client setting to Remove Completed/Failed
Fixes #6322 Fixes #6328 Fixes #6331 Fixes #6337
This commit is contained in:
parent
e9dffb4819
commit
9a395b52ac
17 changed files with 347 additions and 83 deletions
|
@ -16,4 +16,9 @@
|
|||
color: #3a3f51;
|
||||
font-size: 21px;
|
||||
line-height: inherit;
|
||||
|
||||
&.small {
|
||||
color: #909293;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { sizes } from 'Helpers/Props';
|
||||
import styles from './FieldSet.css';
|
||||
|
||||
class FieldSet extends Component {
|
||||
|
@ -9,13 +11,14 @@ class FieldSet extends Component {
|
|||
|
||||
render() {
|
||||
const {
|
||||
size,
|
||||
legend,
|
||||
children
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<fieldset className={styles.fieldSet}>
|
||||
<legend className={styles.legend}>
|
||||
<legend className={classNames(styles.legend, (size === sizes.SMALL) && styles.small)}>
|
||||
{legend}
|
||||
</legend>
|
||||
{children}
|
||||
|
@ -26,8 +29,13 @@ class FieldSet extends Component {
|
|||
}
|
||||
|
||||
FieldSet.propTypes = {
|
||||
size: PropTypes.oneOf(sizes.all).isRequired,
|
||||
legend: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
|
||||
children: PropTypes.node
|
||||
};
|
||||
|
||||
FieldSet.defaultProps = {
|
||||
size: sizes.MEDIUM
|
||||
};
|
||||
|
||||
export default FieldSet;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
|
@ -13,7 +14,7 @@ import ModalBody from 'Components/Modal/ModalBody';
|
|||
import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import { inputTypes, kinds, sizes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './EditDownloadClientModalContent.css';
|
||||
|
||||
|
@ -45,7 +46,10 @@ class EditDownloadClientModalContent extends Component {
|
|||
implementationName,
|
||||
name,
|
||||
enable,
|
||||
protocol,
|
||||
priority,
|
||||
removeCompletedDownloads,
|
||||
removeFailedDownloads,
|
||||
fields,
|
||||
message
|
||||
} = item;
|
||||
|
@ -136,6 +140,38 @@ class EditDownloadClientModalContent extends Component {
|
|||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FieldSet
|
||||
size={sizes.SMALL}
|
||||
legend={translate('CompletedDownloadHandling')}
|
||||
>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('RemoveCompleted')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="removeCompletedDownloads"
|
||||
helpText={translate('RemoveCompletedDownloadsHelpText')}
|
||||
{...removeCompletedDownloads}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
{
|
||||
protocol.value !== 'torrent' &&
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('RemoveFailed')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="removeFailedDownloads"
|
||||
helpText={translate('RemoveFailedDownloadsHelpText')}
|
||||
{...removeFailedDownloads}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
}
|
||||
</FieldSet>
|
||||
|
||||
</Form>
|
||||
}
|
||||
</ModalBody>
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import { inputTypes, sizes } from 'Helpers/Props';
|
||||
import { inputTypes, kinds, sizes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
function DownloadClientOptions(props) {
|
||||
|
@ -34,11 +35,15 @@ function DownloadClientOptions(props) {
|
|||
}
|
||||
|
||||
{
|
||||
hasSettings && !isFetching && !error &&
|
||||
hasSettings && !isFetching && !error && advancedSettings &&
|
||||
<div>
|
||||
<FieldSet legend={translate('CompletedDownloadHandling')}>
|
||||
<Form>
|
||||
<FormGroup size={sizes.MEDIUM}>
|
||||
<FormGroup
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>{translate('Enable')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
|
@ -50,22 +55,6 @@ function DownloadClientOptions(props) {
|
|||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>{translate('Remove')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="removeCompletedDownloads"
|
||||
helpText={translate('RemoveCompletedDownloadsHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.removeCompletedDownloads}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
|
@ -102,23 +91,10 @@ function DownloadClientOptions(props) {
|
|||
{...settings.autoRedownloadFailed}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>{translate('Remove')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="removeFailedDownloads"
|
||||
helpText={translate('RemoveFailedDownloadsHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.removeFailedDownloads}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
<Alert kind={kinds.INFO}>
|
||||
{translate('RemoveDownloadsAlert')}
|
||||
</Alert>
|
||||
</FieldSet>
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Datastore.Migration;
|
||||
using NzbDrone.Core.Download.Clients.RTorrent;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.Datastore.Migration
|
||||
{
|
||||
[TestFixture]
|
||||
public class cdh_per_downloadclientFixture : MigrationTest<cdh_per_downloadclient>
|
||||
{
|
||||
[Test]
|
||||
public void should_set_cdh_to_enabled()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("DownloadClients").Row(new
|
||||
{
|
||||
Enable = 1,
|
||||
Name = "Deluge",
|
||||
Implementation = "Deluge",
|
||||
Priority = 1,
|
||||
Settings = new DelugeSettings85
|
||||
{
|
||||
Host = "127.0.0.1",
|
||||
MovieCategory = "abc",
|
||||
UrlBase = "/my/"
|
||||
}.ToJson(),
|
||||
ConfigContract = "DelugeSettings"
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query<DownloadClientDefinition158>("SELECT * FROM DownloadClients");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().RemoveCompletedDownloads.Should().BeFalse();
|
||||
items.First().RemoveFailedDownloads.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_set_cdh_to_disabled_when_globally_disabled()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Config").Row(new
|
||||
{
|
||||
Key = "removecompleteddownloads",
|
||||
Value = "True"
|
||||
});
|
||||
|
||||
c.Insert.IntoTable("DownloadClients").Row(new
|
||||
{
|
||||
Enable = 1,
|
||||
Name = "Deluge",
|
||||
Implementation = "Deluge",
|
||||
Priority = 1,
|
||||
Settings = new DelugeSettings85
|
||||
{
|
||||
Host = "127.0.0.1",
|
||||
MovieCategory = "abc",
|
||||
UrlBase = "/my/"
|
||||
}.ToJson(),
|
||||
ConfigContract = "DelugeSettings"
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query<DownloadClientDefinition158>("SELECT * FROM DownloadClients");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().RemoveCompletedDownloads.Should().BeTrue();
|
||||
items.First().RemoveFailedDownloads.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_disable_remove_for_existing_rtorrent()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("DownloadClients").Row(new
|
||||
{
|
||||
Enable = 1,
|
||||
Name = "RTorrent",
|
||||
Implementation = "RTorrent",
|
||||
Priority = 1,
|
||||
Settings = new RTorrentSettings
|
||||
{
|
||||
Host = "127.0.0.1",
|
||||
MovieCategory = "abc",
|
||||
UrlBase = "/my/"
|
||||
}.ToJson(),
|
||||
ConfigContract = "RTorrentSettings"
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query<DownloadClientDefinition158>("SELECT * FROM DownloadClients");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().RemoveCompletedDownloads.Should().BeFalse();
|
||||
items.First().RemoveFailedDownloads.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
public class DownloadClientDefinition158
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public bool Enable { get; set; }
|
||||
public int Priority { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Implementation { get; set; }
|
||||
public JsonElement Settings { get; set; }
|
||||
public string ConfigContract { get; set; }
|
||||
public bool RemoveCompletedDownloads { get; set; }
|
||||
public bool RemoveFailedDownloads { get; set; }
|
||||
}
|
||||
|
||||
public class DelugeSettings85
|
||||
{
|
||||
public string Host { get; set; }
|
||||
public int Port { get; set; }
|
||||
public string UrlBase { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string MovieCategory { get; set; }
|
||||
public int RecentTvPriority { get; set; }
|
||||
public int OlderTvPriority { get; set; }
|
||||
public bool UseSsl { get; set; }
|
||||
}
|
||||
}
|
|
@ -192,13 +192,6 @@ namespace NzbDrone.Core.Configuration
|
|||
set { SetValue("WhitelistedHardcodedSubs", value); }
|
||||
}
|
||||
|
||||
public bool RemoveCompletedDownloads
|
||||
{
|
||||
get { return GetValueBoolean("RemoveCompletedDownloads", false); }
|
||||
|
||||
set { SetValue("RemoveCompletedDownloads", value); }
|
||||
}
|
||||
|
||||
public bool AutoRedownloadFailed
|
||||
{
|
||||
get { return GetValueBoolean("AutoRedownloadFailed", true); }
|
||||
|
@ -206,13 +199,6 @@ namespace NzbDrone.Core.Configuration
|
|||
set { SetValue("AutoRedownloadFailed", value); }
|
||||
}
|
||||
|
||||
public bool RemoveFailedDownloads
|
||||
{
|
||||
get { return GetValueBoolean("RemoveFailedDownloads", true); }
|
||||
|
||||
set { SetValue("RemoveFailedDownloads", value); }
|
||||
}
|
||||
|
||||
public bool CreateEmptyMovieFolders
|
||||
{
|
||||
get { return GetValueBoolean("CreateEmptyMovieFolders", false); }
|
||||
|
|
|
@ -21,10 +21,8 @@ namespace NzbDrone.Core.Configuration
|
|||
|
||||
//Completed/Failed Download Handling (Download client)
|
||||
bool EnableCompletedDownloadHandling { get; set; }
|
||||
bool RemoveCompletedDownloads { get; set; }
|
||||
|
||||
bool AutoRedownloadFailed { get; set; }
|
||||
bool RemoveFailedDownloads { get; set; }
|
||||
|
||||
//Media Management
|
||||
bool AutoUnmonitorPreviouslyDownloadedMovies { get; set; }
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
using System.Data;
|
||||
using System.Linq;
|
||||
using FluentMigrator;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(200)]
|
||||
public class cdh_per_downloadclient : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("DownloadClients")
|
||||
.AddColumn("RemoveCompletedDownloads").AsBoolean().NotNullable().WithDefaultValue(true)
|
||||
.AddColumn("RemoveFailedDownloads").AsBoolean().NotNullable().WithDefaultValue(true);
|
||||
|
||||
Execute.WithConnection(MoveRemoveSettings);
|
||||
}
|
||||
|
||||
private void MoveRemoveSettings(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
var removeCompletedDownloads = false;
|
||||
var removeFailedDownloads = true;
|
||||
|
||||
using (var removeCompletedDownloadsCmd = conn.CreateCommand(tran, "SELECT Value FROM Config WHERE Key = 'removecompleteddownloads'"))
|
||||
{
|
||||
if ((removeCompletedDownloadsCmd.ExecuteScalar() as string)?.ToLower() == "true")
|
||||
{
|
||||
removeCompletedDownloads = true;
|
||||
}
|
||||
}
|
||||
|
||||
using (var removeFailedDownloadsCmd = conn.CreateCommand(tran, "SELECT Value FROM Config WHERE Key = 'removefaileddownloads'"))
|
||||
{
|
||||
if ((removeFailedDownloadsCmd.ExecuteScalar() as string)?.ToLower() == "false")
|
||||
{
|
||||
removeFailedDownloads = false;
|
||||
}
|
||||
}
|
||||
|
||||
using (var updateClientCmd = conn.CreateCommand(tran, $"UPDATE DownloadClients SET RemoveCompletedDownloads = (CASE WHEN Implementation IN (\"RTorrent\", \"Flood\") THEN 0 ELSE ? END), RemoveFailedDownloads = ?"))
|
||||
{
|
||||
updateClientCmd.AddParameter(removeCompletedDownloads ? 1 : 0);
|
||||
updateClientCmd.AddParameter(removeFailedDownloads ? 1 : 0);
|
||||
updateClientCmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
using (var removeConfigCmd = conn.CreateCommand(tran, $"DELETE FROM Config WHERE Key IN ('removecompleteddownloads', 'removefaileddownloads')"))
|
||||
{
|
||||
removeConfigCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using FluentMigrator;
|
||||
using System.Data;
|
||||
using FluentMigrator;
|
||||
using FluentMigrator.Builders.Create;
|
||||
using FluentMigrator.Builders.Create.Table;
|
||||
using FluentMigrator.Runner;
|
||||
|
@ -16,6 +17,15 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
|
|||
return expressionRoot.Table(name).WithColumn("Id").AsInt32().PrimaryKey().Identity();
|
||||
}
|
||||
|
||||
public static IDbCommand CreateCommand(this IDbConnection conn, IDbTransaction tran, string query)
|
||||
{
|
||||
var command = conn.CreateCommand();
|
||||
command.Transaction = tran;
|
||||
command.CommandText = query;
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
public static void AddParameter(this System.Data.IDbCommand command, object value)
|
||||
{
|
||||
var parameter = command.CreateParameter();
|
||||
|
|
|
@ -18,8 +18,10 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
|||
public class Flood : TorrentClientBase<FloodSettings>
|
||||
{
|
||||
private readonly IFloodProxy _proxy;
|
||||
private readonly IDownloadSeedConfigProvider _downloadSeedConfigProvider;
|
||||
|
||||
public Flood(IFloodProxy proxy,
|
||||
IDownloadSeedConfigProvider downloadSeedConfigProvider,
|
||||
ITorrentFileInfoReader torrentFileInfoReader,
|
||||
IHttpClient httpClient,
|
||||
IConfigService configService,
|
||||
|
@ -30,6 +32,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
|||
: base(torrentFileInfoReader, httpClient, configService, namingConfigService, diskProvider, remotePathMappingService, logger)
|
||||
{
|
||||
_proxy = proxy;
|
||||
_downloadSeedConfigProvider = downloadSeedConfigProvider;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> HandleTags(RemoteMovie remoteMovie, FloodSettings settings)
|
||||
|
@ -78,8 +81,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
|||
}
|
||||
|
||||
public override string Name => "Flood";
|
||||
public override ProviderMessage Message => new ProviderMessage("Radarr is unable to remove torrents that have finished seeding when using Flood", ProviderMessageType.Warning);
|
||||
|
||||
public override ProviderMessage Message => new ProviderMessage("Radarr will handle automatic removal of torrents based on the current seed criteria in Settings -> Indexers", ProviderMessageType.Info);
|
||||
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, byte[] fileContent)
|
||||
{
|
||||
_proxy.AddTorrentByFile(Convert.ToBase64String(fileContent), HandleTags(remoteMovie, Settings), Settings);
|
||||
|
@ -120,6 +122,8 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
|||
TotalSize = properties.SizeBytes,
|
||||
SeedRatio = properties.Ratio,
|
||||
Message = properties.Message,
|
||||
CanMoveFiles = false,
|
||||
CanBeRemoved = false,
|
||||
};
|
||||
|
||||
if (properties.Eta > 0)
|
||||
|
@ -144,7 +148,28 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
|||
item.Status = DownloadItemStatus.Paused;
|
||||
}
|
||||
|
||||
item.CanMoveFiles = item.CanBeRemoved = false;
|
||||
if (item.Status == DownloadItemStatus.Completed)
|
||||
{
|
||||
// Grab cached seedConfig
|
||||
var seedConfig = _downloadSeedConfigProvider.GetSeedConfiguration(item.DownloadId);
|
||||
|
||||
if (seedConfig != null)
|
||||
{
|
||||
if (item.SeedRatio >= seedConfig.Ratio)
|
||||
{
|
||||
// Check if seed ratio reached
|
||||
item.CanMoveFiles = item.CanBeRemoved = true;
|
||||
}
|
||||
else if (properties.DateFinished != null && properties.DateFinished > 0)
|
||||
{
|
||||
// Check if seed time reached
|
||||
if ((DateTimeOffset.Now - DateTimeOffset.FromUnixTimeSeconds((long)properties.DateFinished)) >= seedConfig.SeedTime)
|
||||
{
|
||||
item.CanMoveFiles = item.CanBeRemoved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
items.Add(item);
|
||||
}
|
||||
|
|
|
@ -31,5 +31,9 @@ namespace NzbDrone.Core.Download.Clients.Flood.Types
|
|||
|
||||
[JsonProperty(PropertyName = "tags")]
|
||||
public List<string> Tags { get; set; }
|
||||
|
||||
// added in Flood 4.5
|
||||
[JsonProperty(PropertyName = "dateFinished")]
|
||||
public long? DateFinished { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
|
@ -7,5 +7,7 @@ namespace NzbDrone.Core.Download
|
|||
{
|
||||
public DownloadProtocol Protocol { get; set; }
|
||||
public int Priority { get; set; } = 1;
|
||||
public bool RemoveCompletedDownloads { get; set; } = true;
|
||||
public bool RemoveFailedDownloads { get; set; } = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,38 +27,65 @@ namespace NzbDrone.Core.Download
|
|||
{
|
||||
var trackedDownload = message.TrackedDownload;
|
||||
|
||||
if (trackedDownload == null || !trackedDownload.DownloadItem.CanBeRemoved || _configService.RemoveFailedDownloads == false)
|
||||
if (trackedDownload == null ||
|
||||
message.TrackedDownload.DownloadItem.Removed ||
|
||||
!trackedDownload.DownloadItem.CanBeRemoved)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveFromDownloadClient(trackedDownload);
|
||||
var downloadClient = _downloadClientProvider.Get(message.TrackedDownload.DownloadClient);
|
||||
var definition = downloadClient.Definition as DownloadClientDefinition;
|
||||
|
||||
if (!definition.RemoveFailedDownloads)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveFromDownloadClient(trackedDownload, downloadClient);
|
||||
}
|
||||
|
||||
public void Handle(DownloadCompletedEvent message)
|
||||
{
|
||||
if (_configService.RemoveCompletedDownloads &&
|
||||
!message.TrackedDownload.DownloadItem.Removed &&
|
||||
message.TrackedDownload.DownloadItem.CanBeRemoved &&
|
||||
message.TrackedDownload.DownloadItem.Status != DownloadItemStatus.Downloading)
|
||||
var trackedDownload = message.TrackedDownload;
|
||||
var downloadClient = _downloadClientProvider.Get(trackedDownload.DownloadClient);
|
||||
var definition = downloadClient.Definition as DownloadClientDefinition;
|
||||
|
||||
MarkItemAsImported(trackedDownload, downloadClient);
|
||||
|
||||
if (trackedDownload.DownloadItem.Removed ||
|
||||
!trackedDownload.DownloadItem.CanBeRemoved ||
|
||||
trackedDownload.DownloadItem.Status == DownloadItemStatus.Downloading)
|
||||
{
|
||||
RemoveFromDownloadClient(message.TrackedDownload);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
if (!definition.RemoveCompletedDownloads)
|
||||
{
|
||||
MarkItemAsImported(message.TrackedDownload);
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveFromDownloadClient(message.TrackedDownload, downloadClient);
|
||||
}
|
||||
|
||||
public void Handle(DownloadCanBeRemovedEvent message)
|
||||
{
|
||||
// Already verified that it can be removed, just needs to be removed
|
||||
RemoveFromDownloadClient(message.TrackedDownload);
|
||||
var trackedDownload = message.TrackedDownload;
|
||||
var downloadClient = _downloadClientProvider.Get(trackedDownload.DownloadClient);
|
||||
var definition = downloadClient.Definition as DownloadClientDefinition;
|
||||
|
||||
if (trackedDownload.DownloadItem.Removed ||
|
||||
!trackedDownload.DownloadItem.CanBeRemoved ||
|
||||
!definition.RemoveCompletedDownloads)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveFromDownloadClient(message.TrackedDownload, downloadClient);
|
||||
}
|
||||
|
||||
private void RemoveFromDownloadClient(TrackedDownload trackedDownload)
|
||||
private void RemoveFromDownloadClient(TrackedDownload trackedDownload, IDownloadClient downloadClient)
|
||||
{
|
||||
var downloadClient = _downloadClientProvider.Get(trackedDownload.DownloadClient);
|
||||
try
|
||||
{
|
||||
_logger.Debug("[{0}] Removing download from {1} history", trackedDownload.DownloadItem.Title, trackedDownload.DownloadItem.DownloadClientInfo.Name);
|
||||
|
@ -75,9 +102,8 @@ namespace NzbDrone.Core.Download
|
|||
}
|
||||
}
|
||||
|
||||
private void MarkItemAsImported(TrackedDownload trackedDownload)
|
||||
private void MarkItemAsImported(TrackedDownload trackedDownload, IDownloadClient downloadClient)
|
||||
{
|
||||
var downloadClient = _downloadClientProvider.Get(trackedDownload.DownloadClient);
|
||||
try
|
||||
{
|
||||
_logger.Debug("[{0}] Marking download as imported from {1}", trackedDownload.DownloadItem.Title, trackedDownload.DownloadItem.DownloadClientInfo.Name);
|
||||
|
|
|
@ -47,7 +47,6 @@ namespace NzbDrone.Core.Download
|
|||
public void Execute(ProcessMonitoredDownloadsCommand message)
|
||||
{
|
||||
var enableCompletedDownloadHandling = _configService.EnableCompletedDownloadHandling;
|
||||
var removeCompletedDownloads = _configService.RemoveCompletedDownloads;
|
||||
var trackedDownloads = _trackedDownloadService.GetTrackedDownloads()
|
||||
.Where(t => t.IsTrackable)
|
||||
.ToList();
|
||||
|
@ -72,10 +71,7 @@ namespace NzbDrone.Core.Download
|
|||
}
|
||||
|
||||
// Imported downloads are no longer trackable so process them after processing trackable downloads
|
||||
if (removeCompletedDownloads)
|
||||
{
|
||||
RemoveCompletedDownloads();
|
||||
}
|
||||
RemoveCompletedDownloads();
|
||||
|
||||
_eventAggregator.PublishEvent(new DownloadsProcessedEvent());
|
||||
}
|
||||
|
|
|
@ -785,10 +785,13 @@
|
|||
"RemotePathMappingCheckWrongOSPath": "Remote download client {0} places downloads in {1} but this is not a valid {2} path. Review your remote path mappings and download client settings.",
|
||||
"RemotePathMappings": "Remote Path Mappings",
|
||||
"Remove": "Remove",
|
||||
"RemoveCompleted": "Remove Completed",
|
||||
"RemoveCompletedDownloadsHelpText": "Remove imported downloads from download client history",
|
||||
"RemovedFromTaskQueue": "Removed from task queue",
|
||||
"RemovedMovieCheckMultipleMessage": "Movies {0} were removed from TMDb",
|
||||
"RemovedMovieCheckSingleMessage": "Movie {0} was removed from TMDb",
|
||||
"RemoveDownloadsAlert": "The Remove settings were moved to the individual Download Client settings in the table above.",
|
||||
"RemoveFailed": "Remove Failed",
|
||||
"RemoveFailedDownloadsHelpText": "Remove failed downloads from download client history",
|
||||
"RemoveFilter": "Remove filter",
|
||||
"RemoveFromBlocklist": "Remove from blocklist",
|
||||
|
|
|
@ -8,11 +8,9 @@ namespace Radarr.Api.V3.Config
|
|||
public string DownloadClientWorkingFolders { get; set; }
|
||||
|
||||
public bool EnableCompletedDownloadHandling { get; set; }
|
||||
public bool RemoveCompletedDownloads { get; set; }
|
||||
public int CheckForFinishedDownloadInterval { get; set; }
|
||||
|
||||
public bool AutoRedownloadFailed { get; set; }
|
||||
public bool RemoveFailedDownloads { get; set; }
|
||||
}
|
||||
|
||||
public static class DownloadClientConfigResourceMapper
|
||||
|
@ -24,11 +22,9 @@ namespace Radarr.Api.V3.Config
|
|||
DownloadClientWorkingFolders = model.DownloadClientWorkingFolders,
|
||||
|
||||
EnableCompletedDownloadHandling = model.EnableCompletedDownloadHandling,
|
||||
RemoveCompletedDownloads = model.RemoveCompletedDownloads,
|
||||
CheckForFinishedDownloadInterval = model.CheckForFinishedDownloadInterval,
|
||||
|
||||
AutoRedownloadFailed = model.AutoRedownloadFailed,
|
||||
RemoveFailedDownloads = model.RemoveFailedDownloads
|
||||
AutoRedownloadFailed = model.AutoRedownloadFailed
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ namespace Radarr.Api.V3.DownloadClient
|
|||
public bool Enable { get; set; }
|
||||
public DownloadProtocol Protocol { get; set; }
|
||||
public int Priority { get; set; }
|
||||
public bool RemoveCompletedDownloads { get; set; }
|
||||
public bool RemoveFailedDownloads { get; set; }
|
||||
}
|
||||
|
||||
public class DownloadClientResourceMapper : ProviderResourceMapper<DownloadClientResource, DownloadClientDefinition>
|
||||
|
@ -24,6 +26,8 @@ namespace Radarr.Api.V3.DownloadClient
|
|||
resource.Enable = definition.Enable;
|
||||
resource.Protocol = definition.Protocol;
|
||||
resource.Priority = definition.Priority;
|
||||
resource.RemoveCompletedDownloads = definition.RemoveCompletedDownloads;
|
||||
resource.RemoveFailedDownloads = definition.RemoveFailedDownloads;
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
@ -40,6 +44,8 @@ namespace Radarr.Api.V3.DownloadClient
|
|||
definition.Enable = resource.Enable;
|
||||
definition.Protocol = resource.Protocol;
|
||||
definition.Priority = resource.Priority;
|
||||
definition.RemoveCompletedDownloads = resource.RemoveCompletedDownloads;
|
||||
definition.RemoveFailedDownloads = resource.RemoveFailedDownloads;
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue