mirror of
https://github.com/Radarr/Radarr.git
synced 2024-08-16 23:39:44 +02:00
New: Rework List sync interval logic
* New: Rework List sync interval logic (cherry picked from commit c522cd120d08757e7e43c2348be4d7f05a254fac) * Minor alignment with Sonarr * Remove ListUpdateInterval --------- Co-authored-by: Qstick <qstick@gmail.com>
This commit is contained in:
parent
148ee5983d
commit
bd1844030d
@ -3,3 +3,9 @@
|
||||
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.message {
|
||||
composes: alert from '~Components/Alert.css';
|
||||
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'deleteButton': string;
|
||||
'message': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
|
@ -14,6 +14,7 @@ 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 formatShortTimeSpan from 'Utilities/Date/formatShortTimeSpan';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './EditImportListModalContent.css';
|
||||
|
||||
@ -42,6 +43,7 @@ function EditImportListModalContent(props) {
|
||||
name,
|
||||
enabled,
|
||||
enableAuto,
|
||||
minRefreshInterval,
|
||||
monitor,
|
||||
minimumAvailability,
|
||||
qualityProfileId,
|
||||
@ -85,6 +87,14 @@ function EditImportListModalContent(props) {
|
||||
{message.value.message}
|
||||
</Alert>
|
||||
}
|
||||
|
||||
<Alert
|
||||
kind={kinds.INFO}
|
||||
className={styles.message}
|
||||
>
|
||||
{translate('ListWillRefreshEveryInterp', [formatShortTimeSpan(minRefreshInterval.value)])}
|
||||
</Alert>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Name')}</FormLabel>
|
||||
|
||||
|
@ -4,6 +4,7 @@ import Card from 'Components/Card';
|
||||
import Label from 'Components/Label';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import formatShortTimeSpan from 'Utilities/Date/formatShortTimeSpan';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import EditImportListModalConnector from './EditImportListModalConnector';
|
||||
import styles from './ImportList.css';
|
||||
@ -56,7 +57,8 @@ class ImportList extends Component {
|
||||
id,
|
||||
name,
|
||||
enabled,
|
||||
enableAuto
|
||||
enableAuto,
|
||||
minRefreshInterval
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@ -96,6 +98,12 @@ class ImportList extends Component {
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className={styles.enabled}>
|
||||
<Label kind={kinds.INFO} title='List Refresh Interval'>
|
||||
{`${translate('Refresh')}: ${formatShortTimeSpan(minRefreshInterval)}`}
|
||||
</Label>
|
||||
</div>
|
||||
|
||||
<EditImportListModalConnector
|
||||
id={id}
|
||||
isOpen={this.state.isEditImportListModalOpen}
|
||||
@ -122,6 +130,7 @@ ImportList.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
enabled: PropTypes.bool.isRequired,
|
||||
enableAuto: PropTypes.bool.isRequired,
|
||||
minRefreshInterval: PropTypes.string.isRequired,
|
||||
onConfirmDeleteImportList: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
|
@ -46,23 +46,6 @@ function ImportListOptions(props) {
|
||||
{
|
||||
hasSettings && !isFetching && !error &&
|
||||
<Form>
|
||||
<FormGroup
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>{translate('ListUpdateInterval')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
name="importListSyncInterval"
|
||||
min={6}
|
||||
unit="hours"
|
||||
helpText={translate('ImportListSyncIntervalHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.importListSyncInterval}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
|
25
frontend/src/Utilities/Date/formatShortTimeSpan.js
Normal file
25
frontend/src/Utilities/Date/formatShortTimeSpan.js
Normal file
@ -0,0 +1,25 @@
|
||||
import moment from 'moment';
|
||||
|
||||
function formatShortTimeSpan(timeSpan) {
|
||||
if (!timeSpan) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const duration = moment.duration(timeSpan);
|
||||
|
||||
const hours = Math.floor(duration.asHours());
|
||||
const minutes = Math.floor(duration.asMinutes());
|
||||
const seconds = Math.floor(duration.asSeconds());
|
||||
|
||||
if (hours > 0) {
|
||||
return `${hours} hour(s)`;
|
||||
}
|
||||
|
||||
if (minutes > 0) {
|
||||
return `${minutes} minute(s)`;
|
||||
}
|
||||
|
||||
return `${seconds} second(s)`;
|
||||
}
|
||||
|
||||
export default formatShortTimeSpan;
|
@ -27,7 +27,7 @@ public void Setup()
|
||||
_blockedLists = new List<ImportListStatus>();
|
||||
|
||||
Mocker.GetMock<IImportListFactory>()
|
||||
.Setup(v => v.Enabled())
|
||||
.Setup(v => v.Enabled(It.IsAny<bool>()))
|
||||
.Returns(_importLists);
|
||||
|
||||
Mocker.GetMock<IImportListStatusService>()
|
||||
@ -183,7 +183,7 @@ public void should_return_all_results_for_all_lists()
|
||||
|
||||
var listResult = Subject.Fetch();
|
||||
listResult.AnyFailure.Should().BeFalse();
|
||||
listResult.Movies.Count.Should().Be(10);
|
||||
listResult.Movies.Count.Should().Be(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ public void Setup()
|
||||
};
|
||||
|
||||
Mocker.GetMock<IImportListFactory>()
|
||||
.Setup(v => v.Enabled())
|
||||
.Setup(v => v.Enabled(It.IsAny<bool>()))
|
||||
.Returns(_importLists);
|
||||
|
||||
Mocker.GetMock<IImportExclusionsService>()
|
||||
@ -347,7 +347,7 @@ public void should_add_new_movies_from_enabled_lists_to_library()
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_add_duplicate_movies_from_seperate_lists()
|
||||
public void should_not_add_duplicate_movies_from_separate_lists()
|
||||
{
|
||||
_list2Movies.ForEach(m => m.ListId = 2);
|
||||
_importListFetch.Movies.ForEach(m => m.ListId = 1);
|
||||
@ -384,7 +384,7 @@ public void should_not_add_movie_from_on_exclusion_list()
|
||||
Subject.Execute(_commandAll);
|
||||
|
||||
Mocker.GetMock<IAddMovieService>()
|
||||
.Verify(v => v.AddMovies(It.Is<List<Movie>>(s => s.Count == 7 && !s.Any(m => m.TmdbId == _existingMovies[0].TmdbId)), true), Times.Once());
|
||||
.Verify(v => v.AddMovies(It.Is<List<Movie>>(s => s.Count == 7 && s.All(m => m.TmdbId != _existingMovies[0].TmdbId)), true), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -406,7 +406,7 @@ public void should_not_add_movie_that_exists_in_library()
|
||||
Subject.Execute(_commandAll);
|
||||
|
||||
Mocker.GetMock<IAddMovieService>()
|
||||
.Verify(v => v.AddMovies(It.Is<List<Movie>>(s => s.Count == 7 && !s.Any(m => m.TmdbId == _existingMovies[0].TmdbId)), true), Times.Once());
|
||||
.Verify(v => v.AddMovies(It.Is<List<Movie>>(s => s.Count == 7 && s.All(m => m.TmdbId != _existingMovies[0].TmdbId)), true), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,13 +116,6 @@ public int AvailabilityDelay
|
||||
set { SetValue("AvailabilityDelay", value); }
|
||||
}
|
||||
|
||||
public int ImportListSyncInterval
|
||||
{
|
||||
get { return GetValueInt("ImportListSyncInterval", 24); }
|
||||
|
||||
set { SetValue("ImportListSyncInterval", value); }
|
||||
}
|
||||
|
||||
public string ListSyncLevel
|
||||
{
|
||||
get { return GetValue("ListSyncLevel", "disabled"); }
|
||||
|
@ -60,7 +60,6 @@ public interface IConfigService
|
||||
bool AllowHardcodedSubs { get; set; }
|
||||
string WhitelistedHardcodedSubs { get; set; }
|
||||
|
||||
int ImportListSyncInterval { get; set; }
|
||||
string ListSyncLevel { get; set; }
|
||||
string ImportExclusions { get; set; }
|
||||
|
||||
|
18
src/NzbDrone.Core/Datastore/Migration/224_list_sync_time.cs
Normal file
18
src/NzbDrone.Core/Datastore/Migration/224_list_sync_time.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(224)]
|
||||
public class list_sync_time : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Delete.Column("LastSyncListInfo").FromTable("ImportListStatus");
|
||||
|
||||
Alter.Table("ImportListStatus").AddColumn("LastInfoSync").AsDateTimeOffset().Nullable();
|
||||
|
||||
Delete.FromTable("Config").Row(new { Key = "importlistsyncinterval" });
|
||||
}
|
||||
}
|
||||
}
|
@ -80,6 +80,7 @@ public static void Map()
|
||||
Mapper.Entity<ImportListDefinition>("ImportLists").RegisterModel()
|
||||
.Ignore(x => x.ImplementationName)
|
||||
.Ignore(i => i.ListType)
|
||||
.Ignore(i => i.MinRefreshInterval)
|
||||
.Ignore(i => i.Enable);
|
||||
|
||||
Mapper.Entity<NotificationDefinition>("Notifications").RegisterModel()
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
@ -10,6 +11,7 @@ public class CouchPotatoImport : HttpImportListBase<CouchPotatoSettings>
|
||||
public override string Name => "CouchPotato";
|
||||
|
||||
public override ImportListType ListType => ImportListType.Program;
|
||||
public override TimeSpan MinRefreshInterval => TimeSpan.FromMinutes(30);
|
||||
public override bool Enabled => true;
|
||||
public override bool EnableAuto => false;
|
||||
|
||||
|
@ -66,6 +66,15 @@ public ImportListFetchResult Fetch()
|
||||
_logger.ProgressInfo("Syncing Movies for List: {0}", importList.Name);
|
||||
|
||||
var importListLocal = importList;
|
||||
|
||||
var importListStatus = _importListStatusService.GetLastSyncListInfo(importListLocal.Definition.Id);
|
||||
|
||||
if (importListStatus.HasValue && DateTime.UtcNow < importListStatus + importListLocal.MinRefreshInterval)
|
||||
{
|
||||
_logger.Trace("Skipping refresh of Import List {0} due to minimum refresh inverval", importListLocal.Definition.Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
var blockedLists = _importListStatusService.GetBlockedProviders().ToDictionary(v => v.ProviderId, v => v);
|
||||
|
||||
if (blockedLists.TryGetValue(importList.Definition.Id, out var blockedListStatus))
|
||||
@ -88,7 +97,7 @@ public ImportListFetchResult Fetch()
|
||||
if (!importListReports.AnyFailure)
|
||||
{
|
||||
var alreadyMapped = result.Movies.Where(x => importListReports.Movies.Any(r => r.TmdbId == x.TmdbId));
|
||||
var listMovies = MapMovieReports(importListReports.Movies.Where(x => !result.Movies.Any(r => r.TmdbId == x.TmdbId)).ToList()).Where(x => x.TmdbId > 0).ToList();
|
||||
var listMovies = MapMovieReports(importListReports.Movies.Where(x => result.Movies.All(r => r.TmdbId != x.TmdbId)).ToList()).Where(x => x.TmdbId > 0).ToList();
|
||||
|
||||
listMovies.AddRange(alreadyMapped);
|
||||
listMovies = listMovies.DistinctBy(x => x.TmdbId).ToList();
|
||||
@ -99,6 +108,8 @@ public ImportListFetchResult Fetch()
|
||||
}
|
||||
|
||||
result.AnyFailure |= importListReports.AnyFailure;
|
||||
|
||||
_importListStatusService.UpdateListSyncStatus(importList.Definition.Id);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@ -112,6 +123,8 @@ public ImportListFetchResult Fetch()
|
||||
|
||||
Task.WaitAll(taskList.ToArray());
|
||||
|
||||
result.Movies = result.Movies.DistinctBy(r => new { r.TmdbId, r.ImdbId, r.Title }).ToList();
|
||||
|
||||
_logger.Debug("Found {0} reports for all lists", result.Movies.Count);
|
||||
|
||||
return result;
|
||||
@ -151,6 +164,8 @@ public ImportListFetchResult FetchSingleList(ImportListDefinition definition)
|
||||
}
|
||||
|
||||
result.AnyFailure |= importListReports.AnyFailure;
|
||||
|
||||
_importListStatusService.UpdateListSyncStatus(importList.Definition.Id);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@ -158,6 +173,8 @@ public ImportListFetchResult FetchSingleList(ImportListDefinition definition)
|
||||
_logger.Error(e, "Error during Import List Sync for list {0}", importList.Name);
|
||||
}
|
||||
|
||||
result.Movies = result.Movies.DistinctBy(r => new { r.TmdbId, r.ImdbId, r.Title }).ToList();
|
||||
|
||||
_logger.Debug("Found {0} reports for list {1}", result.Movies.Count, importList.Name);
|
||||
|
||||
return result;
|
||||
@ -166,9 +183,9 @@ public ImportListFetchResult FetchSingleList(ImportListDefinition definition)
|
||||
private List<ImportListMovie> MapMovieReports(List<ImportListMovie> reports)
|
||||
{
|
||||
var mappedMovies = reports.Select(m => _movieSearch.MapMovieToTmdbMovie(new MovieMetadata { Title = m.Title, TmdbId = m.TmdbId, ImdbId = m.ImdbId, Year = m.Year }))
|
||||
.Where(x => x != null)
|
||||
.DistinctBy(x => x.TmdbId)
|
||||
.ToList();
|
||||
.Where(x => x != null)
|
||||
.DistinctBy(x => x.TmdbId)
|
||||
.ToList();
|
||||
|
||||
_movieMetadataService.UpsertMany(mappedMovies);
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.ImportLists
|
||||
@ -8,6 +9,7 @@ public interface IImportList : IProvider
|
||||
bool EnableAuto { get; }
|
||||
|
||||
ImportListType ListType { get; }
|
||||
TimeSpan MinRefreshInterval { get; }
|
||||
ImportListFetchResult Fetch();
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ public abstract class ImportListBase<TSettings> : IImportList
|
||||
public abstract string Name { get; }
|
||||
|
||||
public abstract ImportListType ListType { get; }
|
||||
public abstract TimeSpan MinRefreshInterval { get; }
|
||||
public abstract bool Enabled { get; }
|
||||
public abstract bool EnableAuto { get; }
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
@ -21,5 +22,6 @@ public ImportListDefinition()
|
||||
public override bool Enable => Enabled;
|
||||
|
||||
public ImportListType ListType { get; set; }
|
||||
public TimeSpan MinRefreshInterval { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -9,23 +9,24 @@ namespace NzbDrone.Core.ImportLists
|
||||
{
|
||||
public interface IImportListFactory : IProviderFactory<IImportList, ImportListDefinition>
|
||||
{
|
||||
List<IImportList> Enabled();
|
||||
List<IImportList> Enabled(bool filterBlockedImportLists = true);
|
||||
List<IImportList> Discoverable();
|
||||
}
|
||||
|
||||
public class ImportListFactory : ProviderFactory<IImportList, ImportListDefinition>, IImportListFactory
|
||||
{
|
||||
private readonly IImportListRepository _providerRepository;
|
||||
private readonly IImportListStatusService _importListStatusService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public ImportListFactory(IImportListRepository providerRepository,
|
||||
public ImportListFactory(IImportListStatusService importListStatusService,
|
||||
IImportListRepository providerRepository,
|
||||
IEnumerable<IImportList> providers,
|
||||
IServiceProvider container,
|
||||
IEventAggregator eventAggregator,
|
||||
Logger logger)
|
||||
: base(providerRepository, providers, container, eventAggregator, logger)
|
||||
{
|
||||
_providerRepository = providerRepository;
|
||||
_importListStatusService = importListStatusService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@ -39,18 +40,42 @@ public override void SetProviderCharacteristics(IImportList provider, ImportList
|
||||
base.SetProviderCharacteristics(provider, definition);
|
||||
|
||||
definition.ListType = provider.ListType;
|
||||
definition.MinRefreshInterval = provider.MinRefreshInterval;
|
||||
}
|
||||
|
||||
public List<IImportList> Enabled()
|
||||
public List<IImportList> Enabled(bool filterBlockedImportLists = true)
|
||||
{
|
||||
var enabledImporters = GetAvailableProviders().Where(n => ((ImportListDefinition)n.Definition).Enabled);
|
||||
return enabledImporters.ToList();
|
||||
var enabledImportLists = GetAvailableProviders().Where(n => ((ImportListDefinition)n.Definition).Enabled);
|
||||
|
||||
if (filterBlockedImportLists)
|
||||
{
|
||||
return FilterBlockedImportLists(enabledImportLists).ToList();
|
||||
}
|
||||
|
||||
return enabledImportLists.ToList();
|
||||
}
|
||||
|
||||
public List<IImportList> Discoverable()
|
||||
{
|
||||
var enabledImporters = GetAvailableProviders().Where(n => (n.GetType() == typeof(RadarrList.RadarrListImport) || n.GetType() == typeof(TMDb.Popular.TMDbPopularImport)));
|
||||
return enabledImporters.ToList();
|
||||
var enabledImportLists = GetAvailableProviders().Where(n => n.GetType() == typeof(RadarrList.RadarrListImport) || n.GetType() == typeof(TMDb.Popular.TMDbPopularImport));
|
||||
|
||||
return enabledImportLists.ToList();
|
||||
}
|
||||
|
||||
private IEnumerable<IImportList> FilterBlockedImportLists(IEnumerable<IImportList> importLists)
|
||||
{
|
||||
var blockedImportLists = _importListStatusService.GetBlockedProviders().ToDictionary(v => v.ProviderId, v => v);
|
||||
|
||||
foreach (var importList in importLists)
|
||||
{
|
||||
if (blockedImportLists.TryGetValue(importList.Definition.Id, out var blockedImportListStatus))
|
||||
{
|
||||
_logger.Debug("Temporarily ignoring import list {0} till {1} due to recent failures.", importList.Definition.Name, blockedImportListStatus.DisabledTill.Value.ToLocalTime());
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return importList;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
using NzbDrone.Core.Movies;
|
||||
using System;
|
||||
using NzbDrone.Core.ThingiProvider.Status;
|
||||
|
||||
namespace NzbDrone.Core.ImportLists
|
||||
{
|
||||
public class ImportListStatus : ProviderStatusBase
|
||||
{
|
||||
public Movie LastSyncListInfo { get; set; }
|
||||
public DateTime? LastInfoSync { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.ThingiProvider.Status;
|
||||
|
||||
namespace NzbDrone.Core.ImportLists
|
||||
{
|
||||
public interface IImportListStatusService : IProviderStatusServiceBase<ImportListStatus>
|
||||
{
|
||||
Movie GetLastSyncListInfo(int importListId);
|
||||
DateTime? GetLastSyncListInfo(int importListId);
|
||||
|
||||
void UpdateListSyncStatus(int importListId, Movie listItemInfo);
|
||||
void UpdateListSyncStatus(int importListId);
|
||||
}
|
||||
|
||||
public class ImportListStatusService : ProviderStatusServiceBase<IImportList, ImportListStatus>, IImportListStatusService
|
||||
@ -20,18 +20,18 @@ public ImportListStatusService(IImportListStatusRepository providerStatusReposit
|
||||
{
|
||||
}
|
||||
|
||||
public Movie GetLastSyncListInfo(int importListId)
|
||||
public DateTime? GetLastSyncListInfo(int importListId)
|
||||
{
|
||||
return GetProviderStatus(importListId).LastSyncListInfo;
|
||||
return GetProviderStatus(importListId).LastInfoSync;
|
||||
}
|
||||
|
||||
public void UpdateListSyncStatus(int importListId, Movie listItemInfo)
|
||||
public void UpdateListSyncStatus(int importListId)
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
var status = GetProviderStatus(importListId);
|
||||
|
||||
status.LastSyncListInfo = listItemInfo;
|
||||
status.LastInfoSync = DateTime.UtcNow;
|
||||
|
||||
_providerStatusRepository.Upsert(status);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ public class PlexImport : HttpImportListBase<PlexListSettings>
|
||||
{
|
||||
public readonly IPlexTvService _plexTvService;
|
||||
public override ImportListType ListType => ImportListType.Plex;
|
||||
public override TimeSpan MinRefreshInterval => TimeSpan.FromHours(6);
|
||||
|
||||
public PlexImport(IPlexTvService plexTvService,
|
||||
IHttpClient httpClient,
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
@ -12,6 +13,7 @@ public class RSSImport : HttpImportListBase<RSSImportSettings>
|
||||
public override string Name => "RSS List";
|
||||
|
||||
public override ImportListType ListType => ImportListType.Advanced;
|
||||
public override TimeSpan MinRefreshInterval => TimeSpan.FromHours(12);
|
||||
public override bool Enabled => true;
|
||||
public override bool EnableAuto => false;
|
||||
|
||||
|
@ -19,6 +19,7 @@ public class RadarrImport : ImportListBase<RadarrSettings>
|
||||
public override bool EnableAuto => false;
|
||||
|
||||
public override ImportListType ListType => ImportListType.Program;
|
||||
public override TimeSpan MinRefreshInterval => TimeSpan.FromMinutes(15);
|
||||
|
||||
public RadarrImport(IRadarrV3Proxy radarrV3Proxy,
|
||||
IImportListStatusService importListStatusService,
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
@ -12,6 +13,7 @@ public class RadarrListImport : HttpImportListBase<RadarrListSettings>
|
||||
public override string Name => "Custom Lists";
|
||||
|
||||
public override ImportListType ListType => ImportListType.Advanced;
|
||||
public override TimeSpan MinRefreshInterval => TimeSpan.FromHours(12);
|
||||
public override bool Enabled => true;
|
||||
public override bool EnableAuto => false;
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cloud;
|
||||
@ -15,6 +16,7 @@ public class IMDbListImport : HttpImportListBase<IMDbListSettings>
|
||||
public override string Name => "IMDb Lists";
|
||||
|
||||
public override ImportListType ListType => ImportListType.Other;
|
||||
public override TimeSpan MinRefreshInterval => TimeSpan.FromHours(12);
|
||||
public override bool Enabled => true;
|
||||
public override bool EnableAuto => false;
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cloud;
|
||||
using NzbDrone.Common.Http;
|
||||
@ -13,6 +14,8 @@ public class StevenLu2Import : HttpImportListBase<StevenLu2Settings>
|
||||
public override string Name => "StevenLu List";
|
||||
|
||||
public override ImportListType ListType => ImportListType.Other;
|
||||
public override TimeSpan MinRefreshInterval => TimeSpan.FromHours(12);
|
||||
|
||||
public override bool Enabled => true;
|
||||
public override bool EnableAuto => false;
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
@ -9,6 +10,7 @@ public class PlexRssImport : RssImportBase<PlexRssImportSettings>
|
||||
{
|
||||
public override string Name => "Plex Watchlist RSS";
|
||||
public override ImportListType ListType => ImportListType.Plex;
|
||||
public override TimeSpan MinRefreshInterval => TimeSpan.FromHours(6);
|
||||
|
||||
public PlexRssImport(IHttpClient httpClient,
|
||||
IImportListStatusService importListStatusService,
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
@ -10,6 +11,7 @@ public class StevenLuImport : HttpImportListBase<StevenLuSettings>
|
||||
public override string Name => "StevenLu Custom";
|
||||
|
||||
public override ImportListType ListType => ImportListType.Advanced;
|
||||
public override TimeSpan MinRefreshInterval => TimeSpan.FromHours(24);
|
||||
public override bool Enabled => true;
|
||||
public override bool EnableAuto => false;
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cloud;
|
||||
using NzbDrone.Common.Http;
|
||||
@ -11,6 +12,7 @@ public abstract class TMDbImportListBase<TSettings> : HttpImportListBase<TSettin
|
||||
where TSettings : TMDbSettingsBase<TSettings>, new()
|
||||
{
|
||||
public override ImportListType ListType => ImportListType.TMDB;
|
||||
public override TimeSpan MinRefreshInterval => TimeSpan.FromHours(12);
|
||||
|
||||
public readonly ISearchForNewMovie _skyhookProxy;
|
||||
public readonly IHttpRequestBuilderFactory _requestBuilder;
|
||||
|
@ -15,6 +15,7 @@ public abstract class TraktImportBase<TSettings> : HttpImportListBase<TSettings>
|
||||
public ITraktProxy _traktProxy;
|
||||
private readonly IImportListRepository _importListRepository;
|
||||
public override ImportListType ListType => ImportListType.Trakt;
|
||||
public override TimeSpan MinRefreshInterval => TimeSpan.FromHours(12);
|
||||
|
||||
protected TraktImportBase(IImportListRepository importListRepository,
|
||||
ITraktProxy traktProxy,
|
||||
|
@ -121,7 +121,7 @@ public void Handle(ApplicationStartedEvent message)
|
||||
|
||||
new ScheduledTask
|
||||
{
|
||||
Interval = GetImportListSyncInterval(),
|
||||
Interval = 5,
|
||||
TypeName = typeof(ImportListSyncCommand).FullName
|
||||
},
|
||||
|
||||
@ -210,14 +210,6 @@ private int GetRefreshMonitoredInterval()
|
||||
return interval;
|
||||
}
|
||||
|
||||
private int GetImportListSyncInterval()
|
||||
{
|
||||
// Enforce 6 hour min on list sync
|
||||
var interval = Math.Max(_configService.ImportListSyncInterval, 6);
|
||||
|
||||
return interval * 60;
|
||||
}
|
||||
|
||||
public void Handle(CommandExecutedEvent message)
|
||||
{
|
||||
var scheduledTask = _scheduledTaskRepository.All().SingleOrDefault(c => c.TypeName == message.Command.Body.GetType().FullName);
|
||||
@ -239,19 +231,15 @@ public void HandleAsync(ConfigSavedEvent message)
|
||||
var rss = _scheduledTaskRepository.GetDefinition(typeof(RssSyncCommand));
|
||||
rss.Interval = GetRssSyncInterval();
|
||||
|
||||
var importList = _scheduledTaskRepository.GetDefinition(typeof(ImportListSyncCommand));
|
||||
importList.Interval = GetImportListSyncInterval();
|
||||
|
||||
var backup = _scheduledTaskRepository.GetDefinition(typeof(BackupCommand));
|
||||
backup.Interval = GetBackupInterval();
|
||||
|
||||
var refreshMonitoredDownloads = _scheduledTaskRepository.GetDefinition(typeof(RefreshMonitoredDownloadsCommand));
|
||||
refreshMonitoredDownloads.Interval = GetRefreshMonitoredInterval();
|
||||
|
||||
_scheduledTaskRepository.UpdateMany(new List<ScheduledTask> { rss, importList, refreshMonitoredDownloads, backup });
|
||||
_scheduledTaskRepository.UpdateMany(new List<ScheduledTask> { rss, refreshMonitoredDownloads, backup });
|
||||
|
||||
_cache.Find(rss.TypeName).Interval = rss.Interval;
|
||||
_cache.Find(importList.TypeName).Interval = importList.Interval;
|
||||
_cache.Find(backup.TypeName).Interval = backup.Interval;
|
||||
_cache.Find(refreshMonitoredDownloads.TypeName).Interval = refreshMonitoredDownloads.Interval;
|
||||
}
|
||||
|
@ -416,7 +416,6 @@
|
||||
"ImportListMultipleMissingRoots": "Multiple root folders are missing for import lists: {0}",
|
||||
"ImportListStatusCheckAllClientMessage": "All lists are unavailable due to failures",
|
||||
"ImportListStatusCheckSingleClientMessage": "Lists unavailable due to failures: {0}",
|
||||
"ImportListSyncIntervalHelpText": "How often Radarr syncs with your lists. Minimum value of 6 hours",
|
||||
"ImportMechanismHealthCheckMessage": "Enable Completed Download Handling",
|
||||
"ImportMovies": "Import Movies",
|
||||
"ImportNotForDownloads": "Do not use for importing downloads from your download client, this is only for existing organized libraries, not unsorted files.",
|
||||
@ -484,11 +483,12 @@
|
||||
"Links": "Links",
|
||||
"List": "List",
|
||||
"ListExclusions": "List Exclusions",
|
||||
"ListRefreshInterval": "List Refresh Interval",
|
||||
"ListSettings": "List Settings",
|
||||
"ListSyncLevelHelpText": "Movies in library will be handled based on your selection if they fall off or do not appear on your list(s)",
|
||||
"ListSyncLevelHelpTextWarning": "Movie files will be permanently deleted, this can result in wiping your library if your lists are empty",
|
||||
"ListTagsHelpText": "Tags list items will be added with",
|
||||
"ListUpdateInterval": "List Update Interval",
|
||||
"ListWillRefreshEveryInterp": "List will refresh every {0}",
|
||||
"Lists": "Lists",
|
||||
"ListsSettingsSummary": "Import Lists, list exclusions",
|
||||
"Loading": "Loading",
|
||||
|
@ -1,6 +1,5 @@
|
||||
using NzbDrone.Core.Configuration;
|
||||
using Radarr.Http;
|
||||
using Radarr.Http.Validation;
|
||||
|
||||
namespace Radarr.Api.V3.Config
|
||||
{
|
||||
@ -11,8 +10,6 @@ public class ImportListConfigController : ConfigController<ImportListConfigResou
|
||||
public ImportListConfigController(IConfigService configService)
|
||||
: base(configService)
|
||||
{
|
||||
SharedValidator.RuleFor(c => c.ImportListSyncInterval)
|
||||
.IsValidImportListSyncInterval();
|
||||
}
|
||||
|
||||
protected override ImportListConfigResource ToResource(IConfigService model)
|
||||
|
@ -5,7 +5,6 @@ namespace Radarr.Api.V3.Config
|
||||
{
|
||||
public class ImportListConfigResource : RestResource
|
||||
{
|
||||
public int ImportListSyncInterval { get; set; }
|
||||
public string ListSyncLevel { get; set; }
|
||||
public string ImportExclusions { get; set; }
|
||||
}
|
||||
@ -16,7 +15,6 @@ public static ImportListConfigResource ToResource(IConfigService model)
|
||||
{
|
||||
return new ImportListConfigResource
|
||||
{
|
||||
ImportListSyncInterval = model.ImportListSyncInterval,
|
||||
ListSyncLevel = model.ListSyncLevel,
|
||||
ImportExclusions = model.ImportExclusions
|
||||
};
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using NzbDrone.Core.ImportLists;
|
||||
using NzbDrone.Core.Movies;
|
||||
|
||||
@ -14,6 +15,7 @@ public class ImportListResource : ProviderResource<ImportListResource>
|
||||
public MovieStatusType MinimumAvailability { get; set; }
|
||||
public ImportListType ListType { get; set; }
|
||||
public int ListOrder { get; set; }
|
||||
public TimeSpan MinRefreshInterval { get; set; }
|
||||
}
|
||||
|
||||
public class ImportListResourceMapper : ProviderResourceMapper<ImportListResource, ImportListDefinition>
|
||||
@ -36,6 +38,7 @@ public override ImportListResource ToResource(ImportListDefinition definition)
|
||||
resource.MinimumAvailability = definition.MinimumAvailability;
|
||||
resource.ListType = definition.ListType;
|
||||
resource.ListOrder = (int)definition.ListType;
|
||||
resource.MinRefreshInterval = definition.MinRefreshInterval;
|
||||
|
||||
return resource;
|
||||
}
|
||||
@ -57,6 +60,7 @@ public override ImportListDefinition ToModel(ImportListResource resource)
|
||||
definition.ProfileId = resource.QualityProfileId;
|
||||
definition.MinimumAvailability = resource.MinimumAvailability;
|
||||
definition.ListType = resource.ListType;
|
||||
definition.MinRefreshInterval = resource.MinRefreshInterval;
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
using FluentValidation.Validators;
|
||||
|
||||
namespace Radarr.Http.Validation
|
||||
{
|
||||
public class ImportListSyncIntervalValidator : PropertyValidator
|
||||
{
|
||||
protected override string GetDefaultMessageTemplate() => "Must be greater than 6 hours";
|
||||
|
||||
protected override bool IsValid(PropertyValidatorContext context)
|
||||
{
|
||||
if (context.PropertyValue == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var value = (int)context.PropertyValue;
|
||||
|
||||
return value >= 6;
|
||||
}
|
||||
}
|
||||
}
|
@ -36,10 +36,5 @@ public static IRuleBuilderOptions<T, int> IsValidRssSyncInterval<T>(this IRuleBu
|
||||
{
|
||||
return ruleBuilder.SetValidator(new RssSyncIntervalValidator());
|
||||
}
|
||||
|
||||
public static IRuleBuilderOptions<T, int> IsValidImportListSyncInterval<T>(this IRuleBuilder<T, int> ruleBuilder)
|
||||
{
|
||||
return ruleBuilder.SetValidator(new ImportListSyncIntervalValidator());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user