Fixed: Significantly improved api performance.
This commit is contained in:
parent
ff6737314f
commit
a2536deef0
|
@ -1,168 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Marr.Data;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Api.Commands;
|
||||
using NzbDrone.Api.Config;
|
||||
using NzbDrone.Api.Episodes;
|
||||
using NzbDrone.Api.History;
|
||||
using NzbDrone.Api.Indexers;
|
||||
using NzbDrone.Api.Logs;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Api.Profiles;
|
||||
using NzbDrone.Api.RootFolders;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Instrumentation;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Profiles;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Update.Commands;
|
||||
using NzbDrone.Test.Common;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Api.Test.MappingTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ResourceMappingFixture : TestBase
|
||||
{
|
||||
[TestCase(typeof(Core.Tv.Series), typeof(SeriesResource))]
|
||||
[TestCase(typeof(Episode), typeof(EpisodeResource))]
|
||||
[TestCase(typeof(RootFolder), typeof(RootFolderResource))]
|
||||
[TestCase(typeof(NamingConfig), typeof(NamingConfigResource))]
|
||||
// [TestCase(typeof(IndexerDefinition), typeof(IndexerResource))] //TODO: Ignoring because we don't have a good way to ignore properties with value injector
|
||||
[TestCase(typeof(ReleaseInfo), typeof(ReleaseResource))]
|
||||
[TestCase(typeof(ParsedEpisodeInfo), typeof(ReleaseResource))]
|
||||
[TestCase(typeof(DownloadDecision), typeof(ReleaseResource))]
|
||||
[TestCase(typeof(Core.History.History), typeof(HistoryResource))]
|
||||
[TestCase(typeof(Profile), typeof(ProfileResource))]
|
||||
[TestCase(typeof(ProfileQualityItem), typeof(ProfileQualityItemResource))]
|
||||
[TestCase(typeof(Log), typeof(LogResource))]
|
||||
[TestCase(typeof(Command), typeof(CommandResource))]
|
||||
public void matching_fields(Type modelType, Type resourceType)
|
||||
{
|
||||
MappingValidation.ValidateMapping(modelType, resourceType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_map_lazy_loaded_values_should_not_be_inject_if_not_loaded()
|
||||
{
|
||||
var modelWithLazy = new ModelWithLazy()
|
||||
{
|
||||
Guid = new TestLazyLoaded<Guid>()
|
||||
};
|
||||
|
||||
modelWithLazy.InjectTo<ModelWithNoLazy>().Guid.Should().BeEmpty();
|
||||
|
||||
modelWithLazy.Guid.IsLoaded.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_map_lay_loaded_values_should_be_inject_if_loaded()
|
||||
{
|
||||
|
||||
var guid = Guid.NewGuid();
|
||||
|
||||
var modelWithLazy = new ModelWithLazy()
|
||||
{
|
||||
Guid = new LazyLoaded<Guid>(guid)
|
||||
};
|
||||
|
||||
modelWithLazy.InjectTo<ModelWithNoLazy>().Guid.Should().Be(guid);
|
||||
|
||||
modelWithLazy.Guid.IsLoaded.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_map_lists()
|
||||
{
|
||||
var modelList = Builder<TestModel>.CreateListOfSize(10).Build();
|
||||
|
||||
var resourceList = modelList.InjectTo<List<TestResource>>();
|
||||
|
||||
resourceList.Should().HaveSameCount(modelList);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_map_wrapped_models()
|
||||
{
|
||||
var modelList = Builder<TestModel>.CreateListOfSize(10).Build().ToList();
|
||||
|
||||
var wrapper = new TestModelWrapper
|
||||
{
|
||||
TestlList = modelList
|
||||
};
|
||||
|
||||
wrapper.InjectTo<TestResourceWrapper>();
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void should_map_profile()
|
||||
{
|
||||
var profileResource = new ProfileResource
|
||||
{
|
||||
Cutoff = Quality.WEBDL1080p,
|
||||
Items = new List<ProfileQualityItemResource> { new ProfileQualityItemResource { Quality = Quality.WEBDL1080p, Allowed = true } }
|
||||
};
|
||||
|
||||
|
||||
profileResource.InjectTo<Profile>();
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_map_tracked_command()
|
||||
{
|
||||
var commandResource = new CommandModel { Body = new ApplicationUpdateCommand() };
|
||||
commandResource.InjectTo<CommandResource>();
|
||||
}
|
||||
}
|
||||
|
||||
public class ModelWithLazy
|
||||
{
|
||||
public LazyLoaded<Guid> Guid { get; set; }
|
||||
}
|
||||
|
||||
public class ModelWithNoLazy
|
||||
{
|
||||
public Guid Guid { get; set; }
|
||||
}
|
||||
|
||||
public class TestLazyLoaded<T> : LazyLoaded<T>
|
||||
{
|
||||
public override void Prepare(Func<IDataMapper> dataMapperFactory, object parent)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class TestModelWrapper
|
||||
{
|
||||
public List<TestModel> TestlList { get; set; }
|
||||
}
|
||||
|
||||
public class TestResourceWrapper
|
||||
{
|
||||
public List<TestResource> TestList { get; set; }
|
||||
}
|
||||
|
||||
public class TestModel
|
||||
{
|
||||
public string Field1 { get; set; }
|
||||
public string Field2 { get; set; }
|
||||
}
|
||||
|
||||
public class TestResource
|
||||
{
|
||||
public string Field1 { get; set; }
|
||||
public string Field2 { get; set; }
|
||||
}
|
||||
}
|
|
@ -63,13 +63,9 @@
|
|||
<Reference Include="Moq">
|
||||
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Omu.ValueInjecter">
|
||||
<HintPath>..\packages\ValueInjecter.2.3.3\lib\net35\Omu.ValueInjecter.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ClientSchemaTests\SchemaBuilderFixture.cs" />
|
||||
<Compile Include="MappingTests\ResourceMappingFixture.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -4,5 +4,4 @@
|
|||
<package id="Moq" version="4.0.10827" />
|
||||
<package id="NBuilder" version="3.0.1.1" targetFramework="net40" />
|
||||
<package id="NUnit" version="3.2.0" targetFramework="net40" />
|
||||
<package id="ValueInjecter" version="2.3.3" targetFramework="net40" />
|
||||
</packages>
|
|
@ -1,4 +1,5 @@
|
|||
using NzbDrone.Core.Blacklisting;
|
||||
using System;
|
||||
using NzbDrone.Core.Blacklisting;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Api.Blacklist
|
||||
|
@ -24,7 +25,7 @@ namespace NzbDrone.Api.Blacklist
|
|||
SortDirection = pagingResource.SortDirection
|
||||
};
|
||||
|
||||
return ApplyToPage(_blacklistService.Paged, pagingSpec);
|
||||
return ApplyToPage(_blacklistService.Paged, pagingSpec, BlacklistResourceMapper.MapToResource);
|
||||
}
|
||||
|
||||
private void DeleteBlacklist(int id)
|
||||
|
|
|
@ -20,4 +20,28 @@ namespace NzbDrone.Api.Blacklist
|
|||
|
||||
public SeriesResource Series { get; set; }
|
||||
}
|
||||
|
||||
public static class BlacklistResourceMapper
|
||||
{
|
||||
public static BlacklistResource MapToResource(this Core.Blacklisting.Blacklist model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new BlacklistResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
SeriesId = model.SeriesId,
|
||||
EpisodeIds = model.EpisodeIds,
|
||||
SourceTitle = model.SourceTitle,
|
||||
Quality = model.Quality,
|
||||
Date = model.Date,
|
||||
Protocol = model.Protocol,
|
||||
Indexer = model.Indexer,
|
||||
Message = model.Message,
|
||||
|
||||
Series = model.Series.ToResource()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace NzbDrone.Api.Calendar
|
|||
if (queryEnd.HasValue) end = DateTime.Parse(queryEnd.Value);
|
||||
if (queryIncludeUnmonitored.HasValue) includeUnmonitored = Convert.ToBoolean(queryIncludeUnmonitored.Value);
|
||||
|
||||
var resources = ToListResource(() => _episodeService.EpisodesBetweenDates(start, end, includeUnmonitored));
|
||||
var resources = MapToResource(_episodeService.EpisodesBetweenDates(start, end, includeUnmonitored), true, true);
|
||||
|
||||
return resources.OrderBy(e => e.AirDateUtc).ToList();
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ using NzbDrone.Common.EnsureThat;
|
|||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Reflection;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.ClientSchema
|
||||
{
|
||||
|
@ -56,7 +55,7 @@ namespace NzbDrone.Api.ClientSchema
|
|||
return result.OrderBy(r => r.Order).ToList();
|
||||
}
|
||||
|
||||
public static object ReadFormSchema(List<Field> fields, Type targetType, object defaults = null)
|
||||
public static object ReadFromSchema(List<Field> fields, Type targetType)
|
||||
{
|
||||
Ensure.That(targetType, () => targetType).IsNotNull();
|
||||
|
||||
|
@ -64,11 +63,6 @@ namespace NzbDrone.Api.ClientSchema
|
|||
|
||||
var target = Activator.CreateInstance(targetType);
|
||||
|
||||
if (defaults != null)
|
||||
{
|
||||
target.InjectFrom(defaults);
|
||||
}
|
||||
|
||||
foreach (var propertyInfo in properties)
|
||||
{
|
||||
var fieldAttribute = propertyInfo.GetAttribute<FieldDefinitionAttribute>(false);
|
||||
|
@ -146,9 +140,9 @@ namespace NzbDrone.Api.ClientSchema
|
|||
|
||||
}
|
||||
|
||||
public static T ReadFormSchema<T>(List<Field> fields)
|
||||
public static T ReadFromSchema<T>(List<Field> fields)
|
||||
{
|
||||
return (T)ReadFormSchema(fields, typeof(T));
|
||||
return (T)ReadFromSchema(fields, typeof(T));
|
||||
}
|
||||
|
||||
private static List<SelectOption> GetSelectOptions(Type selectOptions)
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Api.Validation;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
|
@ -36,15 +35,13 @@ namespace NzbDrone.Api.Commands
|
|||
|
||||
private CommandResource GetCommand(int id)
|
||||
{
|
||||
return _commandQueueManager.Get(id).InjectTo<CommandResource>();
|
||||
return _commandQueueManager.Get(id).ToResource();
|
||||
}
|
||||
|
||||
private int StartCommand(CommandResource commandResource)
|
||||
{
|
||||
var commandType =
|
||||
_serviceFactory.GetImplementations(typeof (Command))
|
||||
.Single(c => c.Name.Replace("Command", "")
|
||||
.Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase));
|
||||
var commandType = _serviceFactory.GetImplementations(typeof(Command))
|
||||
.Single(c => c.Name.Replace("Command", "").Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
dynamic command = Request.Body.FromJson(commandType);
|
||||
command.Trigger = CommandTrigger.Manual;
|
||||
|
@ -55,14 +52,14 @@ namespace NzbDrone.Api.Commands
|
|||
|
||||
private List<CommandResource> GetStartedCommands()
|
||||
{
|
||||
return ToListResource(_commandQueueManager.GetStarted());
|
||||
return _commandQueueManager.GetStarted().ToResource();
|
||||
}
|
||||
|
||||
public void Handle(CommandUpdatedEvent message)
|
||||
{
|
||||
if (message.Command.Body.SendUpdatesToClient)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Command.InjectTo<CommandResource>());
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Command.ToResource());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
|
@ -9,7 +11,7 @@ namespace NzbDrone.Api.Commands
|
|||
{
|
||||
public string Name { get; set; }
|
||||
public string Message { get; set; }
|
||||
public Command Body { get; set; }
|
||||
public object Body { get; set; }
|
||||
public CommandPriority Priority { get; set; }
|
||||
public CommandStatus Status { get; set; }
|
||||
public DateTime Queued { get; set; }
|
||||
|
@ -70,7 +72,7 @@ namespace NzbDrone.Api.Commands
|
|||
{
|
||||
get
|
||||
{
|
||||
if (Body != null) return Body.SendUpdatesToClient;
|
||||
if (Body != null) return (Body as Command).SendUpdatesToClient;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -82,7 +84,7 @@ namespace NzbDrone.Api.Commands
|
|||
{
|
||||
get
|
||||
{
|
||||
if (Body != null) return Body.UpdateScheduledTask;
|
||||
if (Body != null) return (Body as Command).UpdateScheduledTask;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -92,4 +94,37 @@ namespace NzbDrone.Api.Commands
|
|||
|
||||
public DateTime? LastExecutionTime { get; set; }
|
||||
}
|
||||
|
||||
public static class CommandResourceMapper
|
||||
{
|
||||
public static CommandResource ToResource(this CommandModel model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new CommandResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
Name = model.Name,
|
||||
Message = model.Message,
|
||||
Body = model.Body,
|
||||
Priority = model.Priority,
|
||||
Status = model.Status,
|
||||
Queued = model.QueuedAt,
|
||||
Started = model.StartedAt,
|
||||
Ended = model.EndedAt,
|
||||
Duration = model.Duration,
|
||||
Exception = model.Exception,
|
||||
Trigger = model.Trigger,
|
||||
|
||||
CompletionMessage = model.Body.CompletionMessage,
|
||||
LastExecutionTime = model.Body.LastExecutionTime
|
||||
};
|
||||
}
|
||||
|
||||
public static List<CommandResource> ToResource(this IEnumerable<CommandModel> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,5 +21,10 @@ namespace NzbDrone.Api.Config
|
|||
.SetValidator(pathExistsValidator)
|
||||
.When(c => !string.IsNullOrWhiteSpace(c.DownloadedEpisodesFolder));
|
||||
}
|
||||
|
||||
protected override DownloadClientConfigResource ToResource(IConfigService model)
|
||||
{
|
||||
return DownloadClientConfigResourceMapper.ToResource(model);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Api.Config
|
||||
{
|
||||
|
@ -15,4 +16,23 @@ namespace NzbDrone.Api.Config
|
|||
public bool AutoRedownloadFailed { get; set; }
|
||||
public bool RemoveFailedDownloads { get; set; }
|
||||
}
|
||||
|
||||
public static class DownloadClientConfigResourceMapper
|
||||
{
|
||||
public static DownloadClientConfigResource ToResource(IConfigService model)
|
||||
{
|
||||
return new DownloadClientConfigResource
|
||||
{
|
||||
DownloadedEpisodesFolder = model.DownloadedEpisodesFolder,
|
||||
DownloadClientWorkingFolders = model.DownloadClientWorkingFolders,
|
||||
DownloadedEpisodesScanInterval = model.DownloadedEpisodesScanInterval,
|
||||
|
||||
EnableCompletedDownloadHandling = model.EnableCompletedDownloadHandling,
|
||||
RemoveCompletedDownloads = model.RemoveCompletedDownloads,
|
||||
|
||||
AutoRedownloadFailed = model.AutoRedownloadFailed,
|
||||
RemoveFailedDownloads = model.RemoveFailedDownloads
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ using NzbDrone.Core.Configuration;
|
|||
using NzbDrone.Core.Update;
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.Config
|
||||
{
|
||||
|
@ -50,12 +49,10 @@ namespace NzbDrone.Api.Config
|
|||
|
||||
private HostConfigResource GetHostConfig()
|
||||
{
|
||||
var resource = new HostConfigResource();
|
||||
resource.InjectFrom(_configFileProvider, _configService);
|
||||
var resource = _configFileProvider.ToResource(_configService);
|
||||
resource.Id = 1;
|
||||
|
||||
var user = _userService.FindUser();
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
resource.Username = user.Username;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Authentication;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Update;
|
||||
using NzbDrone.Common.Http.Proxy;
|
||||
|
||||
|
@ -20,7 +21,6 @@ namespace NzbDrone.Api.Config
|
|||
public string LogLevel { get; set; }
|
||||
public string Branch { get; set; }
|
||||
public string ApiKey { get; set; }
|
||||
public bool Torrent { get; set; }
|
||||
public string SslCertHash { get; set; }
|
||||
public string UrlBase { get; set; }
|
||||
public bool UpdateAutomatically { get; set; }
|
||||
|
@ -35,4 +35,40 @@ namespace NzbDrone.Api.Config
|
|||
public string ProxyBypassFilter { get; set; }
|
||||
public bool ProxyBypassLocalAddresses { get; set; }
|
||||
}
|
||||
|
||||
public static class HostConfigResourceMapper
|
||||
{
|
||||
public static HostConfigResource ToResource(this IConfigFileProvider model, IConfigService configService)
|
||||
{
|
||||
// TODO: Clean this mess up. don't mix data from multiple classes, use sub-resources instead?
|
||||
return new HostConfigResource
|
||||
{
|
||||
BindAddress = model.BindAddress,
|
||||
Port = model.Port,
|
||||
SslPort = model.SslPort,
|
||||
EnableSsl = model.EnableSsl,
|
||||
LaunchBrowser = model.LaunchBrowser,
|
||||
AuthenticationMethod = model.AuthenticationMethod,
|
||||
AnalyticsEnabled = model.AnalyticsEnabled,
|
||||
//Username
|
||||
//Password
|
||||
LogLevel = model.LogLevel,
|
||||
Branch = model.Branch,
|
||||
ApiKey = model.ApiKey,
|
||||
SslCertHash = model.SslCertHash,
|
||||
UrlBase = model.UrlBase,
|
||||
UpdateAutomatically = model.UpdateAutomatically,
|
||||
UpdateMechanism = model.UpdateMechanism,
|
||||
UpdateScriptPath = model.UpdateScriptPath,
|
||||
ProxyEnabled = configService.ProxyEnabled,
|
||||
ProxyType = configService.ProxyType,
|
||||
ProxyHostname = configService.ProxyHostname,
|
||||
ProxyPort = configService.ProxyPort,
|
||||
ProxyUsername = configService.ProxyUsername,
|
||||
ProxyPassword = configService.ProxyPassword,
|
||||
ProxyBypassFilter = configService.ProxyBypassFilter,
|
||||
ProxyBypassLocalAddresses = configService.ProxyBypassLocalAddresses
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using FluentValidation;
|
||||
using System;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Api.Validation;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
|
@ -19,5 +20,10 @@ namespace NzbDrone.Api.Config
|
|||
SharedValidator.RuleFor(c => c.RssSyncInterval)
|
||||
.IsValidRssSyncInterval();
|
||||
}
|
||||
|
||||
protected override IndexerConfigResource ToResource(IConfigService model)
|
||||
{
|
||||
return IndexerConfigResourceMapper.ToResource(model);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Api.Config
|
||||
{
|
||||
|
@ -9,4 +10,17 @@ namespace NzbDrone.Api.Config
|
|||
public int Retention { get; set; }
|
||||
public int RssSyncInterval { get; set; }
|
||||
}
|
||||
|
||||
public static class IndexerConfigResourceMapper
|
||||
{
|
||||
public static IndexerConfigResource ToResource(IConfigService model)
|
||||
{
|
||||
return new IndexerConfigResource
|
||||
{
|
||||
MinimumAge = model.MinimumAge,
|
||||
Retention = model.Retention,
|
||||
RssSyncInterval = model.RssSyncInterval,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,5 +14,10 @@ namespace NzbDrone.Api.Config
|
|||
SharedValidator.RuleFor(c => c.FolderChmod).NotEmpty();
|
||||
SharedValidator.RuleFor(c => c.RecycleBin).IsValidPath().SetValidator(pathExistsValidator).When(c => !string.IsNullOrWhiteSpace(c.RecycleBin));
|
||||
}
|
||||
|
||||
protected override MediaManagementConfigResource ToResource(IConfigService model)
|
||||
{
|
||||
return MediaManagementConfigResourceMapper.ToResource(model);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
|
||||
namespace NzbDrone.Api.Config
|
||||
|
@ -22,4 +23,29 @@ namespace NzbDrone.Api.Config
|
|||
public bool CopyUsingHardlinks { get; set; }
|
||||
public bool EnableMediaInfo { get; set; }
|
||||
}
|
||||
|
||||
public static class MediaManagementConfigResourceMapper
|
||||
{
|
||||
public static MediaManagementConfigResource ToResource(IConfigService model)
|
||||
{
|
||||
return new MediaManagementConfigResource
|
||||
{
|
||||
AutoUnmonitorPreviouslyDownloadedEpisodes = model.AutoUnmonitorPreviouslyDownloadedEpisodes,
|
||||
RecycleBin = model.RecycleBin,
|
||||
AutoDownloadPropers = model.AutoDownloadPropers,
|
||||
CreateEmptySeriesFolders = model.CreateEmptySeriesFolders,
|
||||
FileDate = model.FileDate,
|
||||
|
||||
SetPermissionsLinux = model.SetPermissionsLinux,
|
||||
FileChmod = model.FileChmod,
|
||||
FolderChmod = model.FolderChmod,
|
||||
ChownUser = model.ChownUser,
|
||||
ChownGroup = model.ChownGroup,
|
||||
|
||||
SkipFreeSpaceCheckWhenImporting = model.SkipFreeSpaceCheckWhenImporting,
|
||||
CopyUsingHardlinks = model.CopyUsingHardlinks,
|
||||
EnableMediaInfo = model.EnableMediaInfo,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,7 @@ using Nancy.Responses;
|
|||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using Nancy.ModelBinding;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.Config
|
||||
{
|
||||
|
@ -46,7 +44,7 @@ namespace NzbDrone.Api.Config
|
|||
|
||||
private void UpdateNamingConfig(NamingConfigResource resource)
|
||||
{
|
||||
var nameSpec = resource.InjectTo<NamingConfig>();
|
||||
var nameSpec = resource.ToModel();
|
||||
ValidateFormatResult(nameSpec);
|
||||
|
||||
_namingConfigService.Save(nameSpec);
|
||||
|
@ -55,15 +53,13 @@ namespace NzbDrone.Api.Config
|
|||
private NamingConfigResource GetNamingConfig()
|
||||
{
|
||||
var nameSpec = _namingConfigService.GetConfig();
|
||||
var resource = nameSpec.InjectTo<NamingConfigResource>();
|
||||
var resource = nameSpec.ToResource();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(resource.StandardEpisodeFormat))
|
||||
if (resource.StandardEpisodeFormat.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
return resource;
|
||||
}
|
||||
|
||||
var basicConfig = _filenameBuilder.GetBasicNamingConfig(nameSpec);
|
||||
resource.InjectFrom(basicConfig);
|
||||
basicConfig.AddToResource(resource);
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
@ -75,7 +71,7 @@ namespace NzbDrone.Api.Config
|
|||
|
||||
private JsonResponse<NamingSampleResource> GetExamples(NamingConfigResource config)
|
||||
{
|
||||
var nameSpec = config.InjectTo<NamingConfig>();
|
||||
var nameSpec = config.ToModel();
|
||||
var sampleResource = new NamingSampleResource();
|
||||
|
||||
var singleEpisodeSampleResult = _filenameSampleService.GetStandardSample(nameSpec);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Organizer;
|
||||
|
||||
namespace NzbDrone.Api.Config
|
||||
{
|
||||
|
@ -20,4 +21,57 @@ namespace NzbDrone.Api.Config
|
|||
public string Separator { get; set; }
|
||||
public string NumberStyle { get; set; }
|
||||
}
|
||||
|
||||
public static class NamingConfigResourceMapper
|
||||
{
|
||||
public static NamingConfigResource ToResource(this NamingConfig model)
|
||||
{
|
||||
return new NamingConfigResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
RenameEpisodes = model.RenameEpisodes,
|
||||
ReplaceIllegalCharacters = model.ReplaceIllegalCharacters,
|
||||
MultiEpisodeStyle = model.MultiEpisodeStyle,
|
||||
StandardEpisodeFormat = model.StandardEpisodeFormat,
|
||||
DailyEpisodeFormat = model.DailyEpisodeFormat,
|
||||
AnimeEpisodeFormat = model.AnimeEpisodeFormat,
|
||||
SeriesFolderFormat = model.SeriesFolderFormat,
|
||||
SeasonFolderFormat = model.SeasonFolderFormat
|
||||
//IncludeSeriesTitle
|
||||
//IncludeEpisodeTitle
|
||||
//IncludeQuality
|
||||
//ReplaceSpaces
|
||||
//Separator
|
||||
//NumberStyle
|
||||
};
|
||||
}
|
||||
|
||||
public static void AddToResource(this BasicNamingConfig basicNamingConfig, NamingConfigResource resource)
|
||||
{
|
||||
resource.IncludeSeriesTitle = basicNamingConfig.IncludeSeriesTitle;
|
||||
resource.IncludeEpisodeTitle = basicNamingConfig.IncludeEpisodeTitle;
|
||||
resource.IncludeQuality = basicNamingConfig.IncludeQuality;
|
||||
resource.ReplaceSpaces = basicNamingConfig.ReplaceSpaces;
|
||||
resource.Separator = basicNamingConfig.Separator;
|
||||
resource.NumberStyle = basicNamingConfig.NumberStyle;
|
||||
}
|
||||
|
||||
public static NamingConfig ToModel(this NamingConfigResource resource)
|
||||
{
|
||||
return new NamingConfig
|
||||
{
|
||||
Id = resource.Id,
|
||||
|
||||
RenameEpisodes = resource.RenameEpisodes,
|
||||
ReplaceIllegalCharacters = resource.ReplaceIllegalCharacters,
|
||||
MultiEpisodeStyle = resource.MultiEpisodeStyle,
|
||||
StandardEpisodeFormat = resource.StandardEpisodeFormat,
|
||||
DailyEpisodeFormat = resource.DailyEpisodeFormat,
|
||||
AnimeEpisodeFormat = resource.AnimeEpisodeFormat,
|
||||
SeriesFolderFormat = resource.SeriesFolderFormat,
|
||||
SeasonFolderFormat = resource.SeasonFolderFormat
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
using System.Reflection;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.Config
|
||||
{
|
||||
|
@ -27,13 +26,14 @@ namespace NzbDrone.Api.Config
|
|||
|
||||
private TResource GetConfig()
|
||||
{
|
||||
var resource = new TResource();
|
||||
resource.InjectFrom(_configService);
|
||||
var resource = ToResource(_configService);
|
||||
resource.Id = 1;
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected abstract TResource ToResource(IConfigService model);
|
||||
|
||||
private TResource GetConfig(int id)
|
||||
{
|
||||
return GetConfig();
|
||||
|
|
|
@ -1,45 +1,21 @@
|
|||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.Config
|
||||
{
|
||||
public class UiConfigModule : NzbDroneRestModule<UiConfigResource>
|
||||
public class UiConfigModule : NzbDroneConfigModule<UiConfigResource>
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
|
||||
public UiConfigModule(IConfigService configService)
|
||||
: base("/config/ui")
|
||||
: base(configService)
|
||||
{
|
||||
_configService = configService;
|
||||
|
||||
GetResourceSingle = GetUiConfig;
|
||||
GetResourceById = GetUiConfig;
|
||||
UpdateResource = SaveUiConfig;
|
||||
}
|
||||
|
||||
private UiConfigResource GetUiConfig()
|
||||
protected override UiConfigResource ToResource(IConfigService model)
|
||||
{
|
||||
var resource = new UiConfigResource();
|
||||
resource.InjectFrom(_configService);
|
||||
resource.Id = 1;
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
private UiConfigResource GetUiConfig(int id)
|
||||
{
|
||||
return GetUiConfig();
|
||||
}
|
||||
|
||||
private void SaveUiConfig(UiConfigResource resource)
|
||||
{
|
||||
var dictionary = resource.GetType()
|
||||
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
||||
.ToDictionary(prop => prop.Name, prop => prop.GetValue(resource, null));
|
||||
|
||||
_configService.SaveConfigDictionary(dictionary);
|
||||
return UiConfigResourceMapper.ToResource(model);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Api.Config
|
||||
{
|
||||
|
@ -17,4 +18,23 @@ namespace NzbDrone.Api.Config
|
|||
|
||||
public bool EnableColorImpairedMode { get; set; }
|
||||
}
|
||||
|
||||
public static class UiConfigResourceMapper
|
||||
{
|
||||
public static UiConfigResource ToResource(IConfigService model)
|
||||
{
|
||||
return new UiConfigResource
|
||||
{
|
||||
FirstDayOfWeek = model.FirstDayOfWeek,
|
||||
CalendarWeekColumnHeader = model.CalendarWeekColumnHeader,
|
||||
|
||||
ShortDateFormat = model.ShortDateFormat,
|
||||
LongDateFormat = model.LongDateFormat,
|
||||
TimeFormat = model.TimeFormat,
|
||||
ShowRelativeDates = model.ShowRelativeDates,
|
||||
|
||||
EnableColorImpairedMode = model.EnableColorImpairedMode,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.DiskSpace;
|
||||
|
||||
namespace NzbDrone.Api.DiskSpace
|
||||
|
@ -8,15 +9,16 @@ namespace NzbDrone.Api.DiskSpace
|
|||
private readonly IDiskSpaceService _diskSpaceService;
|
||||
|
||||
public DiskSpaceModule(IDiskSpaceService diskSpaceService)
|
||||
:base("diskspace")
|
||||
: base("diskspace")
|
||||
{
|
||||
_diskSpaceService = diskSpaceService;
|
||||
GetResourceAll = GetFreeSpace;
|
||||
}
|
||||
|
||||
|
||||
public List<DiskSpaceResource> GetFreeSpace()
|
||||
{
|
||||
return ToListResource(_diskSpaceService.GetFreeSpace);
|
||||
return _diskSpaceService.GetFreeSpace().ConvertAll(DiskSpaceResourceMapper.MapToResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,4 +10,20 @@ namespace NzbDrone.Api.DiskSpace
|
|||
public long FreeSpace { get; set; }
|
||||
public long TotalSpace { get; set; }
|
||||
}
|
||||
|
||||
public static class DiskSpaceResourceMapper
|
||||
{
|
||||
public static DiskSpaceResource MapToResource(this Core.DiskSpace.DiskSpace model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new DiskSpaceResource
|
||||
{
|
||||
Path = model.Path,
|
||||
Label = model.Label,
|
||||
FreeSpace = model.FreeSpace,
|
||||
TotalSpace = model.TotalSpace
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using NzbDrone.Core.Download;
|
||||
using System;
|
||||
using NzbDrone.Core.Download;
|
||||
|
||||
namespace NzbDrone.Api.DownloadClient
|
||||
{
|
||||
|
@ -9,6 +10,22 @@ namespace NzbDrone.Api.DownloadClient
|
|||
{
|
||||
}
|
||||
|
||||
protected override void MapToResource(DownloadClientResource resource, DownloadClientDefinition definition)
|
||||
{
|
||||
base.MapToResource(resource, definition);
|
||||
|
||||
resource.Enable = definition.Enable;
|
||||
resource.Protocol = definition.Protocol;
|
||||
}
|
||||
|
||||
protected override void MapToModel(DownloadClientDefinition definition, DownloadClientResource resource)
|
||||
{
|
||||
base.MapToModel(definition, resource);
|
||||
|
||||
definition.Enable = resource.Enable;
|
||||
definition.Protocol = resource.Protocol;
|
||||
}
|
||||
|
||||
protected override void Validate(DownloadClientDefinition definition, bool includeWarnings)
|
||||
{
|
||||
if (!definition.Enable) return;
|
||||
|
|
|
@ -5,7 +5,6 @@ using NLog;
|
|||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
@ -14,7 +13,7 @@ using NzbDrone.SignalR;
|
|||
|
||||
namespace NzbDrone.Api.EpisodeFiles
|
||||
{
|
||||
public class EpisodeModule : NzbDroneRestModuleWithSignalR<EpisodeFileResource, EpisodeFile>,
|
||||
public class EpisodeFileModule : NzbDroneRestModuleWithSignalR<EpisodeFileResource, EpisodeFile>,
|
||||
IHandle<EpisodeFileAddedEvent>
|
||||
{
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
|
@ -23,7 +22,7 @@ namespace NzbDrone.Api.EpisodeFiles
|
|||
private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public EpisodeModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
public EpisodeFileModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IMediaFileService mediaFileService,
|
||||
IRecycleBinProvider recycleBinProvider,
|
||||
ISeriesService seriesService,
|
||||
|
@ -47,7 +46,7 @@ namespace NzbDrone.Api.EpisodeFiles
|
|||
var episodeFile = _mediaFileService.Get(id);
|
||||
var series = _seriesService.GetSeries(episodeFile.SeriesId);
|
||||
|
||||
return MapToResource(series, episodeFile);
|
||||
return episodeFile.ToResource(series, _qualityUpgradableSpecification);
|
||||
}
|
||||
|
||||
private List<EpisodeFileResource> GetEpisodeFiles()
|
||||
|
@ -61,8 +60,7 @@ namespace NzbDrone.Api.EpisodeFiles
|
|||
|
||||
var series = _seriesService.GetSeries(seriesId);
|
||||
|
||||
return _mediaFileService.GetFilesBySeries(seriesId)
|
||||
.Select(f => MapToResource(series, f)).ToList();
|
||||
return _mediaFileService.GetFilesBySeries(seriesId).ConvertAll(f => f.ToResource(series, _qualityUpgradableSpecification));
|
||||
}
|
||||
|
||||
private void SetQuality(EpisodeFileResource episodeFileResource)
|
||||
|
@ -83,16 +81,6 @@ namespace NzbDrone.Api.EpisodeFiles
|
|||
_mediaFileService.Delete(episodeFile, DeleteMediaFileReason.Manual);
|
||||
}
|
||||
|
||||
private EpisodeFileResource MapToResource(Core.Tv.Series series, EpisodeFile episodeFile)
|
||||
{
|
||||
var resource = episodeFile.InjectTo<EpisodeFileResource>();
|
||||
resource.Path = Path.Combine(series.Path, episodeFile.RelativePath);
|
||||
|
||||
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(series.Profile.Value, episodeFile.Quality);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void Handle(EpisodeFileAddedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.EpisodeFile.Id);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
|
@ -17,4 +18,47 @@ namespace NzbDrone.Api.EpisodeFiles
|
|||
|
||||
public bool QualityCutoffNotMet { get; set; }
|
||||
}
|
||||
|
||||
public static class EpisodeFileResourceMapper
|
||||
{
|
||||
private static EpisodeFileResource ToResource(this Core.MediaFiles.EpisodeFile model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new EpisodeFileResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
SeriesId = model.SeriesId,
|
||||
SeasonNumber = model.SeasonNumber,
|
||||
RelativePath = model.RelativePath,
|
||||
//Path
|
||||
Size = model.Size,
|
||||
DateAdded = model.DateAdded,
|
||||
SceneName = model.SceneName,
|
||||
Quality = model.Quality,
|
||||
//QualityCutoffNotMet
|
||||
};
|
||||
}
|
||||
|
||||
public static EpisodeFileResource ToResource(this Core.MediaFiles.EpisodeFile model, Core.Tv.Series series, Core.DecisionEngine.IQualityUpgradableSpecification qualityUpgradableSpecification)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new EpisodeFileResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
SeriesId = model.SeriesId,
|
||||
SeasonNumber = model.SeasonNumber,
|
||||
RelativePath = model.RelativePath,
|
||||
Path = Path.Combine(series.Path, model.RelativePath),
|
||||
Size = model.Size,
|
||||
DateAdded = model.DateAdded,
|
||||
SceneName = model.SceneName,
|
||||
Quality = model.Quality,
|
||||
QualityCutoffNotMet = qualityUpgradableSpecification.CutoffNotMet(series.Profile.Value, model.Quality)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace NzbDrone.Api.Episodes
|
|||
|
||||
var seriesId = (int)Request.Query.SeriesId;
|
||||
|
||||
var resources = ToListResource(_episodeService.GetEpisodeBySeries(seriesId));
|
||||
var resources = MapToResource(_episodeService.GetEpisodeBySeries(seriesId), false, true);
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
@ -36,10 +36,5 @@ namespace NzbDrone.Api.Episodes
|
|||
{
|
||||
_episodeService.SetEpisodeMonitored(episodeResource.Id, episodeResource.Monitored);
|
||||
}
|
||||
|
||||
protected override List<EpisodeResource> LoadSeries(List<EpisodeResource> resources)
|
||||
{
|
||||
return resources;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Api.EpisodeFiles;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
|
@ -53,41 +54,65 @@ namespace NzbDrone.Api.Episodes
|
|||
protected EpisodeResource GetEpisode(int id)
|
||||
{
|
||||
var episode = _episodeService.GetEpisode(id);
|
||||
episode.EpisodeFile.LazyLoad();
|
||||
episode.Series = _seriesService.GetSeries(episode.SeriesId);
|
||||
return ToResource(episode);
|
||||
var resource = MapToResource(episode, true, true);
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected override EpisodeResource ToResource<TModel>(TModel model)
|
||||
protected EpisodeResource MapToResource(Episode episode, bool includeSeries, bool includeEpisodeFile)
|
||||
{
|
||||
var resource = base.ToResource(model);
|
||||
var resource = episode.ToResource();
|
||||
|
||||
var episode = model as Episode;
|
||||
if (episode != null)
|
||||
if (includeSeries || includeEpisodeFile)
|
||||
{
|
||||
if (episode.EpisodeFile.IsLoaded && episode.EpisodeFile.Value != null)
|
||||
var series = episode.Series ?? _seriesService.GetSeries(episode.SeriesId);
|
||||
|
||||
if (includeSeries)
|
||||
{
|
||||
resource.EpisodeFile.Path = Path.Combine(episode.Series.Path, episode.EpisodeFile.Value.RelativePath);
|
||||
resource.EpisodeFile.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(episode.Series.Profile.Value, episode.EpisodeFile.Value.Quality);
|
||||
resource.Series = series.ToResource();
|
||||
}
|
||||
if (includeEpisodeFile && episode.EpisodeFileId != 0)
|
||||
{
|
||||
resource.EpisodeFile = episode.EpisodeFile.Value.ToResource(series, _qualityUpgradableSpecification);
|
||||
}
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected override List<EpisodeResource> ToListResource<TModel>(IEnumerable<TModel> modelList)
|
||||
protected List<EpisodeResource> MapToResource(List<Episode> episodes, bool includeSeries, bool includeEpisodeFile)
|
||||
{
|
||||
var resources = base.ToListResource(modelList);
|
||||
var result = episodes.ToResource();
|
||||
|
||||
return LoadSeries(resources);
|
||||
if (includeSeries || includeEpisodeFile)
|
||||
{
|
||||
var seriesDict = new Dictionary<int, Core.Tv.Series>();
|
||||
for (var i = 0; i < episodes.Count; i++)
|
||||
{
|
||||
var episode = episodes[i];
|
||||
var resource = result[i];
|
||||
|
||||
var series = episode.Series ?? seriesDict.GetValueOrDefault(episodes[i].SeriesId) ?? _seriesService.GetSeries(episodes[i].SeriesId);
|
||||
seriesDict[series.Id] = series;
|
||||
|
||||
if (includeSeries)
|
||||
{
|
||||
resource.Series = series.ToResource();
|
||||
}
|
||||
if (includeEpisodeFile && episodes[i].EpisodeFileId != 0)
|
||||
{
|
||||
resource.EpisodeFile = episodes[i].EpisodeFile.Value.ToResource(series, _qualityUpgradableSpecification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Handle(EpisodeGrabbedEvent message)
|
||||
{
|
||||
foreach (var episode in message.Episode.Episodes)
|
||||
{
|
||||
var resource = episode.InjectTo<EpisodeResource>();
|
||||
var resource = episode.ToResource();
|
||||
resource.Grabbed = true;
|
||||
|
||||
BroadcastResourceChange(ModelAction.Updated, resource);
|
||||
|
@ -101,10 +126,5 @@ namespace NzbDrone.Api.Episodes
|
|||
BroadcastResourceChange(ModelAction.Updated, episode.Id);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual List<EpisodeResource> LoadSeries(List<EpisodeResource> resources)
|
||||
{
|
||||
return resources.LoadSubtype<EpisodeResource, SeriesResource, Core.Tv.Series>(e => e.SeriesId, _seriesService.GetSeries).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Api.EpisodeFiles;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Api.Episodes
|
||||
{
|
||||
|
@ -25,8 +28,6 @@ namespace NzbDrone.Api.Episodes
|
|||
public int? SceneEpisodeNumber { get; set; }
|
||||
public int? SceneSeasonNumber { get; set; }
|
||||
public bool UnverifiedSceneNumbering { get; set; }
|
||||
public DateTime? EndTime { get; set; }
|
||||
public DateTime? GrabDate { get; set; }
|
||||
public string SeriesTitle { get; set; }
|
||||
public SeriesResource Series { get; set; }
|
||||
|
||||
|
@ -34,4 +35,44 @@ namespace NzbDrone.Api.Episodes
|
|||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public bool Grabbed { get; set; }
|
||||
}
|
||||
|
||||
public static class EpisodeResourceMapper
|
||||
{
|
||||
public static EpisodeResource ToResource(this Episode model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new EpisodeResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
SeriesId = model.SeriesId,
|
||||
EpisodeFileId = model.EpisodeFileId,
|
||||
SeasonNumber = model.SeasonNumber,
|
||||
EpisodeNumber = model.EpisodeNumber,
|
||||
Title = model.Title,
|
||||
AirDate = model.AirDate,
|
||||
AirDateUtc = model.AirDateUtc,
|
||||
Overview = model.Overview,
|
||||
//EpisodeFile
|
||||
|
||||
HasFile = model.HasFile,
|
||||
Monitored = model.Monitored,
|
||||
AbsoluteEpisodeNumber = model.AbsoluteEpisodeNumber,
|
||||
SceneAbsoluteEpisodeNumber = model.SceneAbsoluteEpisodeNumber,
|
||||
SceneEpisodeNumber = model.SceneEpisodeNumber,
|
||||
SceneSeasonNumber = model.SceneSeasonNumber,
|
||||
UnverifiedSceneNumbering = model.UnverifiedSceneNumbering,
|
||||
SeriesTitle = model.SeriesTitle,
|
||||
//Series = model.Series.MapToResource(),
|
||||
};
|
||||
}
|
||||
|
||||
public static List<EpisodeResource> ToResource(this IEnumerable<Episode> models)
|
||||
{
|
||||
if (models == null) return null;
|
||||
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,10 @@ namespace NzbDrone.Api.Episodes
|
|||
if (Request.Query.SeasonNumber.HasValue)
|
||||
{
|
||||
var seasonNumber = (int)Request.Query.SeasonNumber;
|
||||
return ToListResource(() => _renameEpisodeFileService.GetRenamePreviews(seriesId, seasonNumber));
|
||||
return _renameEpisodeFileService.GetRenamePreviews(seriesId, seasonNumber).ToResource();
|
||||
}
|
||||
|
||||
return ToListResource(() => _renameEpisodeFileService.GetRenamePreviews(seriesId));
|
||||
return _renameEpisodeFileService.GetRenamePreviews(seriesId).ToResource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.REST;
|
||||
|
||||
namespace NzbDrone.Api.Episodes
|
||||
|
@ -13,4 +14,27 @@ namespace NzbDrone.Api.Episodes
|
|||
public string ExistingPath { get; set; }
|
||||
public string NewPath { get; set; }
|
||||
}
|
||||
|
||||
public static class RenameEpisodeResourceMapper
|
||||
{
|
||||
public static RenameEpisodeResource ToResource(this Core.MediaFiles.RenameEpisodeFilePreview model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new RenameEpisodeResource
|
||||
{
|
||||
SeriesId = model.SeriesId,
|
||||
SeasonNumber = model.SeasonNumber,
|
||||
EpisodeNumbers = model.EpisodeNumbers.ToList(),
|
||||
EpisodeFileId = model.EpisodeFileId,
|
||||
ExistingPath = model.ExistingPath,
|
||||
NewPath = model.NewPath
|
||||
};
|
||||
}
|
||||
|
||||
public static List<RenameEpisodeResource> ToResource(this IEnumerable<Core.MediaFiles.RenameEpisodeFilePreview> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Api.Extensions
|
||||
{
|
||||
public static class LazyExtensions
|
||||
{
|
||||
private static readonly ICached<MethodInfo> SetterCache = new Cached<MethodInfo>();
|
||||
|
||||
public static IEnumerable<TParent> LoadSubtype<TParent, TChild, TSourceChild>(this IEnumerable<TParent> parents, Func<TParent, int> foreignKeySelector, Func<IEnumerable<int>, IEnumerable<TSourceChild>> sourceChildSelector)
|
||||
where TSourceChild : ModelBase, new()
|
||||
where TChild : RestResource, new()
|
||||
where TParent : RestResource
|
||||
{
|
||||
var parentList = parents.Where(p => foreignKeySelector(p) != 0).ToList();
|
||||
|
||||
if (!parentList.Any())
|
||||
{
|
||||
return parents;
|
||||
}
|
||||
|
||||
var ids = parentList.Select(foreignKeySelector).Distinct();
|
||||
var childDictionary = sourceChildSelector(ids).ToDictionary(child => child.Id, child => child);
|
||||
|
||||
var childSetter = GetChildSetter<TParent, TChild>();
|
||||
|
||||
foreach (var episode in parentList)
|
||||
{
|
||||
childSetter.Invoke(episode, new object[] { childDictionary[foreignKeySelector(episode)].InjectTo<TChild>() });
|
||||
}
|
||||
|
||||
return parents;
|
||||
}
|
||||
|
||||
|
||||
private static MethodInfo GetChildSetter<TParent, TChild>()
|
||||
where TChild : RestResource
|
||||
where TParent : RestResource
|
||||
{
|
||||
var key = typeof(TChild).FullName + typeof(TParent).FullName;
|
||||
|
||||
return SetterCache.Get(key, () =>
|
||||
{
|
||||
var property = typeof(TParent).GetProperties().Single(c => c.PropertyType == typeof(TChild));
|
||||
return property.GetSetMethod();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ namespace NzbDrone.Api.Health
|
|||
|
||||
private List<HealthResource> GetHealth()
|
||||
{
|
||||
return ToListResource(_healthCheckService.Results);
|
||||
return _healthCheckService.Results().ToResource();
|
||||
}
|
||||
|
||||
public void Handle(HealthCheckCompleteEvent message)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.HealthCheck;
|
||||
|
@ -11,4 +13,26 @@ namespace NzbDrone.Api.Health
|
|||
public string Message { get; set; }
|
||||
public HttpUri WikiUrl { get; set; }
|
||||
}
|
||||
|
||||
public static class HealthResourceMapper
|
||||
{
|
||||
public static HealthResource ToResource(this HealthCheck model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new HealthResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
Type = model.Type,
|
||||
Message = model.Message,
|
||||
WikiUrl = model.WikiUrl
|
||||
};
|
||||
}
|
||||
|
||||
public static List<HealthResource> ToResource(this IEnumerable<HealthCheck> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using Nancy;
|
||||
using NzbDrone.Api.Episodes;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
|
@ -26,15 +28,16 @@ namespace NzbDrone.Api.History
|
|||
Post["/failed"] = x => MarkAsFailed();
|
||||
}
|
||||
|
||||
protected override HistoryResource ToResource<TModel>(TModel model)
|
||||
protected HistoryResource MapToResource(Core.History.History model)
|
||||
{
|
||||
var resource = base.ToResource(model);
|
||||
var resource = model.ToResource();
|
||||
|
||||
var history = model as Core.History.History;
|
||||
resource.Series = model.Series.ToResource();
|
||||
resource.Episode = model.Episode.ToResource();
|
||||
|
||||
if (history != null && history.Series != null)
|
||||
if (model.Series != null)
|
||||
{
|
||||
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(history.Series.Profile.Value, history.Quality);
|
||||
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(model.Series.Profile.Value, model.Quality);
|
||||
}
|
||||
|
||||
return resource;
|
||||
|
@ -64,7 +67,7 @@ namespace NzbDrone.Api.History
|
|||
pagingSpec.FilterExpression = h => h.EpisodeId == i;
|
||||
}
|
||||
|
||||
return ApplyToPage(_historyService.Paged, pagingSpec);
|
||||
return ApplyToPage(_historyService.Paged, pagingSpec, MapToResource);
|
||||
}
|
||||
|
||||
private Response MarkAsFailed()
|
||||
|
|
|
@ -17,8 +17,6 @@ namespace NzbDrone.Api.History
|
|||
public QualityModel Quality { get; set; }
|
||||
public bool QualityCutoffNotMet { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
public string Indexer { get; set; }
|
||||
public string ReleaseGroup { get; set; }
|
||||
public string DownloadId { get; set; }
|
||||
|
||||
public HistoryEventType EventType { get; set; }
|
||||
|
@ -28,4 +26,31 @@ namespace NzbDrone.Api.History
|
|||
public EpisodeResource Episode { get; set; }
|
||||
public SeriesResource Series { get; set; }
|
||||
}
|
||||
|
||||
public static class HistoryResourceMapper
|
||||
{
|
||||
public static HistoryResource ToResource(this Core.History.History model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new HistoryResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
EpisodeId = model.EpisodeId,
|
||||
SeriesId = model.SeriesId,
|
||||
SourceTitle = model.SourceTitle,
|
||||
Quality = model.Quality,
|
||||
//QualityCutoffNotMet
|
||||
Date = model.Date,
|
||||
DownloadId = model.DownloadId,
|
||||
|
||||
EventType = model.EventType,
|
||||
|
||||
Data = model.Data
|
||||
//Episode
|
||||
//Series
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using NzbDrone.Core.Indexers;
|
||||
using System;
|
||||
using NzbDrone.Core.Indexers;
|
||||
|
||||
namespace NzbDrone.Api.Indexers
|
||||
{
|
||||
|
@ -9,6 +10,25 @@ namespace NzbDrone.Api.Indexers
|
|||
{
|
||||
}
|
||||
|
||||
protected override void MapToResource(IndexerResource resource, IndexerDefinition definition)
|
||||
{
|
||||
base.MapToResource(resource, definition);
|
||||
|
||||
resource.EnableRss = definition.EnableRss;
|
||||
resource.EnableSearch = definition.EnableSearch;
|
||||
resource.SupportsRss = definition.SupportsRss;
|
||||
resource.SupportsSearch = definition.SupportsSearch;
|
||||
resource.Protocol = definition.Protocol;
|
||||
}
|
||||
|
||||
protected override void MapToModel(IndexerDefinition definition, IndexerResource resource)
|
||||
{
|
||||
base.MapToModel(definition, resource);
|
||||
|
||||
definition.EnableRss = resource.EnableRss;
|
||||
definition.EnableSearch = resource.EnableSearch;
|
||||
}
|
||||
|
||||
protected override void Validate(IndexerDefinition definition, bool includeWarnings)
|
||||
{
|
||||
if (!definition.Enable) return;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using Omu.ValueInjecter;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Api.Indexers
|
||||
|
@ -25,42 +24,20 @@ namespace NzbDrone.Api.Indexers
|
|||
|
||||
protected virtual ReleaseResource MapDecision(DownloadDecision decision, int initialWeight)
|
||||
{
|
||||
var release = new ReleaseResource();
|
||||
var release = decision.ToResource();
|
||||
|
||||
release.InjectFrom(decision.RemoteEpisode.Release);
|
||||
release.InjectFrom(decision.RemoteEpisode.ParsedEpisodeInfo);
|
||||
release.InjectFrom(decision);
|
||||
release.Rejections = decision.Rejections.Select(r => r.Reason).ToList();
|
||||
release.DownloadAllowed = decision.RemoteEpisode.DownloadAllowed;
|
||||
release.ReleaseWeight = initialWeight;
|
||||
|
||||
if (decision.RemoteEpisode.Series != null)
|
||||
{
|
||||
release.QualityWeight = decision.RemoteEpisode
|
||||
.Series
|
||||
.Profile
|
||||
.Value
|
||||
.Items
|
||||
.FindIndex(v => v.Quality == release.Quality.Quality) * 100;
|
||||
release.QualityWeight = decision.RemoteEpisode.Series
|
||||
.Profile.Value
|
||||
.Items.FindIndex(v => v.Quality == release.Quality.Quality) * 100;
|
||||
}
|
||||
|
||||
release.QualityWeight += release.Quality.Revision.Real * 10;
|
||||
release.QualityWeight += release.Quality.Revision.Version;
|
||||
|
||||
var torrentRelease = decision.RemoteEpisode.Release as TorrentInfo;
|
||||
|
||||
if (torrentRelease != null)
|
||||
{
|
||||
release.Protocol = DownloadProtocol.Torrent;
|
||||
release.Seeders = torrentRelease.Seeders;
|
||||
//TODO: move this up the chains
|
||||
release.Leechers = torrentRelease.Peers - torrentRelease.Seeders;
|
||||
}
|
||||
else
|
||||
{
|
||||
release.Protocol = DownloadProtocol.Usenet;
|
||||
}
|
||||
|
||||
return release;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ using NzbDrone.Core.Download;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Indexers;
|
||||
|
@ -39,9 +38,7 @@ namespace NzbDrone.Api.Indexers
|
|||
{
|
||||
_logger.Info("Release pushed: {0} - {1}", release.Title, release.DownloadUrl);
|
||||
|
||||
var info = release.Protocol == DownloadProtocol.Usenet ?
|
||||
release.InjectTo<ReleaseInfo>() :
|
||||
release.InjectTo<TorrentInfo>();
|
||||
var info = release.ToModel();
|
||||
|
||||
info.Guid = "PUSH-" + info.DownloadUrl;
|
||||
|
||||
|
|
|
@ -5,6 +5,9 @@ using NzbDrone.Api.REST;
|
|||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Api.Indexers
|
||||
{
|
||||
|
@ -20,11 +23,9 @@ namespace NzbDrone.Api.Indexers
|
|||
public int IndexerId { get; set; }
|
||||
public string Indexer { get; set; }
|
||||
public string ReleaseGroup { get; set; }
|
||||
public string SubGroup { get; set; }
|
||||
public string ReleaseHash { get; set; }
|
||||
public string Title { get; set; }
|
||||
public bool FullSeason { get; set; }
|
||||
public bool SceneSource { get; set; }
|
||||
public int SeasonNumber { get; set; }
|
||||
public Language Language { get; set; }
|
||||
public string AirDate { get; set; }
|
||||
|
@ -45,6 +46,8 @@ namespace NzbDrone.Api.Indexers
|
|||
public int ReleaseWeight { get; set; }
|
||||
|
||||
|
||||
public string MagnetUrl { get; set; }
|
||||
public string InfoHash { get; set; }
|
||||
public int? Seeders { get; set; }
|
||||
public int? Leechers { get; set; }
|
||||
public DownloadProtocol Protocol { get; set; }
|
||||
|
@ -74,4 +77,98 @@ namespace NzbDrone.Api.Indexers
|
|||
public bool IsPossibleSpecialEpisode { get; set; }
|
||||
public bool Special { get; set; }
|
||||
}
|
||||
|
||||
public static class ReleaseResourceMapper
|
||||
{
|
||||
public static ReleaseResource ToResource(this DownloadDecision model)
|
||||
{
|
||||
var releaseInfo = model.RemoteEpisode.Release;
|
||||
var parsedEpisodeInfo = model.RemoteEpisode.ParsedEpisodeInfo;
|
||||
var remoteEpisode = model.RemoteEpisode;
|
||||
var torrentInfo = (model.RemoteEpisode.Release as TorrentInfo) ?? new TorrentInfo();
|
||||
|
||||
// TODO: Clean this mess up. don't mix data from multiple classes, use sub-resources instead? (Got a huge Deja Vu, didn't we talk about this already once?)
|
||||
return new ReleaseResource
|
||||
{
|
||||
Guid = releaseInfo.Guid,
|
||||
Quality = parsedEpisodeInfo.Quality,
|
||||
//QualityWeight
|
||||
Age = releaseInfo.Age,
|
||||
AgeHours = releaseInfo.AgeHours,
|
||||
AgeMinutes = releaseInfo.AgeMinutes,
|
||||
Size = releaseInfo.Size,
|
||||
IndexerId = releaseInfo.IndexerId,
|
||||
Indexer = releaseInfo.Indexer,
|
||||
ReleaseGroup = parsedEpisodeInfo.ReleaseGroup,
|
||||
ReleaseHash = parsedEpisodeInfo.ReleaseHash,
|
||||
Title = releaseInfo.Title,
|
||||
FullSeason = parsedEpisodeInfo.FullSeason,
|
||||
SeasonNumber = parsedEpisodeInfo.SeasonNumber,
|
||||
Language = parsedEpisodeInfo.Language,
|
||||
AirDate = parsedEpisodeInfo.AirDate,
|
||||
SeriesTitle = parsedEpisodeInfo.SeriesTitle,
|
||||
EpisodeNumbers = parsedEpisodeInfo.EpisodeNumbers,
|
||||
AbsoluteEpisodeNumbers = parsedEpisodeInfo.AbsoluteEpisodeNumbers,
|
||||
Approved = model.Approved,
|
||||
TemporarilyRejected = model.TemporarilyRejected,
|
||||
Rejected = model.Rejected,
|
||||
TvdbId = releaseInfo.TvdbId,
|
||||
TvRageId = releaseInfo.TvRageId,
|
||||
Rejections = model.Rejections.Select(r => r.Reason).ToList(),
|
||||
PublishDate = releaseInfo.PublishDate,
|
||||
CommentUrl = releaseInfo.CommentUrl,
|
||||
DownloadUrl = releaseInfo.DownloadUrl,
|
||||
InfoUrl = releaseInfo.InfoUrl,
|
||||
DownloadAllowed = remoteEpisode.DownloadAllowed,
|
||||
//ReleaseWeight
|
||||
|
||||
MagnetUrl = torrentInfo.MagnetUrl,
|
||||
InfoHash = torrentInfo.InfoHash,
|
||||
Seeders = torrentInfo.Seeders,
|
||||
Leechers = (torrentInfo.Peers.HasValue && torrentInfo.Seeders.HasValue) ? (torrentInfo.Peers.Value - torrentInfo.Seeders.Value) : (int?)null,
|
||||
Protocol = releaseInfo.DownloadProtocol,
|
||||
|
||||
IsDaily = parsedEpisodeInfo.IsDaily,
|
||||
IsAbsoluteNumbering = parsedEpisodeInfo.IsAbsoluteNumbering,
|
||||
IsPossibleSpecialEpisode = parsedEpisodeInfo.IsPossibleSpecialEpisode,
|
||||
Special = parsedEpisodeInfo.Special,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public static ReleaseInfo ToModel(this ReleaseResource resource)
|
||||
{
|
||||
ReleaseInfo model;
|
||||
|
||||
if (resource.Protocol == DownloadProtocol.Torrent)
|
||||
{
|
||||
model = new TorrentInfo
|
||||
{
|
||||
MagnetUrl = resource.MagnetUrl,
|
||||
InfoHash = resource.InfoHash,
|
||||
Seeders = resource.Seeders,
|
||||
Peers = (resource.Seeders.HasValue && resource.Leechers.HasValue) ? (resource.Seeders + resource.Leechers) : null
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
model = new ReleaseInfo();
|
||||
}
|
||||
|
||||
model.Guid = resource.Guid;
|
||||
model.Title = resource.Title;
|
||||
model.Size = resource.Size;
|
||||
model.DownloadUrl = resource.DownloadUrl;
|
||||
model.InfoUrl = resource.InfoUrl;
|
||||
model.CommentUrl = resource.CommentUrl;
|
||||
model.IndexerId = resource.IndexerId;
|
||||
model.Indexer = resource.Indexer;
|
||||
model.DownloadProtocol = resource.DownloadProtocol;
|
||||
model.TvdbId = resource.TvdbId;
|
||||
model.TvRageId = resource.TvRageId;
|
||||
model.PublishDate = resource.PublishDate;
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Instrumentation;
|
||||
using NzbDrone.Api.Mapping;
|
||||
|
||||
namespace NzbDrone.Api.Logs
|
||||
{
|
||||
|
@ -16,7 +15,7 @@ namespace NzbDrone.Api.Logs
|
|||
|
||||
private PagingResource<LogResource> GetLogs(PagingResource<LogResource> pagingResource)
|
||||
{
|
||||
var pageSpec = pagingResource.InjectTo<PagingSpec<Log>>();
|
||||
var pageSpec = pagingResource.MapToPagingSpec<LogResource, Log>();
|
||||
|
||||
if (pageSpec.SortKey == "time")
|
||||
{
|
||||
|
@ -48,7 +47,7 @@ namespace NzbDrone.Api.Logs
|
|||
}
|
||||
}
|
||||
|
||||
return ApplyToPage(_logService.Paged, pageSpec);
|
||||
return ApplyToPage(_logService.Paged, pageSpec, LogResourceMapper.ToResource);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,6 +11,25 @@ namespace NzbDrone.Api.Logs
|
|||
public string Level { get; set; }
|
||||
public string Logger { get; set; }
|
||||
public string Message { get; set; }
|
||||
public string Method { get; set; }
|
||||
}
|
||||
|
||||
public static class LogResourceMapper
|
||||
{
|
||||
public static LogResource ToResource(this Core.Instrumentation.Log model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new LogResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
Time = model.Time,
|
||||
Exception = model.Exception,
|
||||
ExceptionType = model.ExceptionType,
|
||||
Level = model.Level,
|
||||
Logger = model.Logger,
|
||||
Message = model.Message
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace NzbDrone.Api.ManualImport
|
|||
var downloadIdQuery = Request.Query.downloadId;
|
||||
var downloadId = (string)downloadIdQuery.Value;
|
||||
|
||||
return ToListResource(_manualImportService.GetMediaFiles(folder, downloadId)).Select(AddQualityWeight).ToList();
|
||||
return _manualImportService.GetMediaFiles(folder, downloadId).ToResource().Select(AddQualityWeight).ToList();
|
||||
}
|
||||
|
||||
private ManualImportResource AddQualityWeight(ManualImportResource item)
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.Episodes;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Common.Crypto;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
|
@ -20,13 +22,35 @@ namespace NzbDrone.Api.ManualImport
|
|||
public int QualityWeight { get; set; }
|
||||
public string DownloadId { get; set; }
|
||||
public IEnumerable<Rejection> Rejections { get; set; }
|
||||
|
||||
public int Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.GetHashCode();
|
||||
}
|
||||
|
||||
public static class ManualImportResourceMapper
|
||||
{
|
||||
public static ManualImportResource ToResource(this Core.MediaFiles.EpisodeImport.Manual.ManualImportItem model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new ManualImportResource
|
||||
{
|
||||
Id = HashConverter.GetHashInt31(model.Path),
|
||||
|
||||
Path = model.Path,
|
||||
RelativePath = model.RelativePath,
|
||||
Name = model.Name,
|
||||
Size = model.Size,
|
||||
Series = model.Series.ToResource(),
|
||||
SeasonNumber = model.SeasonNumber,
|
||||
Episodes = model.Episodes.ToResource(),
|
||||
Quality = model.Quality,
|
||||
//QualityWeight
|
||||
DownloadId = model.DownloadId,
|
||||
Rejections = model.Rejections
|
||||
};
|
||||
}
|
||||
|
||||
public static List<ManualImportResource> ToResource(this IEnumerable<Core.MediaFiles.EpisodeImport.Manual.ManualImportItem> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,125 +0,0 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Marr.Data;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.Mapping
|
||||
{
|
||||
public class CloneInjection : ConventionInjection
|
||||
{
|
||||
protected override bool Match(ConventionInfo conventionInfo)
|
||||
{
|
||||
return conventionInfo.SourceProp.Name == conventionInfo.TargetProp.Name &&
|
||||
conventionInfo.SourceProp.Value != null;
|
||||
}
|
||||
|
||||
protected override object SetValue(ConventionInfo conventionInfo)
|
||||
{
|
||||
if (conventionInfo.SourceProp.Type == conventionInfo.TargetProp.Type)
|
||||
return conventionInfo.SourceProp.Value;
|
||||
|
||||
|
||||
if (conventionInfo.SourceProp.Type.IsArray)
|
||||
{
|
||||
var array = (Array)conventionInfo.SourceProp.Value;
|
||||
var clone = (Array)array.Clone();
|
||||
|
||||
for (var index = 0; index < array.Length; index++)
|
||||
{
|
||||
var item = array.GetValue(index);
|
||||
if (!item.GetType().IsValueType && !(item is string))
|
||||
{
|
||||
clone.SetValue(Activator.CreateInstance(item.GetType()).InjectFrom<CloneInjection>(item), index);
|
||||
}
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
if (conventionInfo.SourceProp.Type.IsGenericType)
|
||||
{
|
||||
var genericInterfaces = conventionInfo.SourceProp.Type.GetGenericTypeDefinition().GetInterfaces();
|
||||
if (genericInterfaces.Any(d => d == typeof(IEnumerable)))
|
||||
{
|
||||
return MapLists(conventionInfo);
|
||||
}
|
||||
|
||||
if (genericInterfaces.Any(i => i == typeof(ILazyLoaded)))
|
||||
{
|
||||
return MapLazy(conventionInfo);
|
||||
}
|
||||
|
||||
//unhandled generic type, you could also return null or throw
|
||||
return conventionInfo.SourceProp.Value;
|
||||
}
|
||||
|
||||
//for simple object types create a new instace and apply the clone injection on it
|
||||
return Activator.CreateInstance(conventionInfo.TargetProp.Type)
|
||||
.InjectFrom<CloneInjection>(conventionInfo.SourceProp.Value);
|
||||
}
|
||||
|
||||
private static object MapLazy(ConventionInfo conventionInfo)
|
||||
{
|
||||
var sourceArgument = conventionInfo.SourceProp.Type.GetGenericArguments()[0];
|
||||
|
||||
dynamic lazy = conventionInfo.SourceProp.Value;
|
||||
|
||||
if (lazy.IsLoaded && lazy.Value != null)
|
||||
{
|
||||
if (conventionInfo.TargetProp.Type.IsAssignableFrom(sourceArgument))
|
||||
{
|
||||
return lazy.Value;
|
||||
}
|
||||
|
||||
var genericArgument = conventionInfo.TargetProp.Type;
|
||||
|
||||
if (genericArgument.IsValueType || genericArgument == typeof(string))
|
||||
{
|
||||
return lazy.Value;
|
||||
}
|
||||
|
||||
if (genericArgument.IsGenericType)
|
||||
{
|
||||
if (conventionInfo.SourceProp.Type.GetGenericTypeDefinition().GetInterfaces().Any(d => d == typeof(IEnumerable)))
|
||||
{
|
||||
return MapLists(genericArgument, lazy.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return Activator.CreateInstance(genericArgument).InjectFrom((object)lazy.Value);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static object MapLists(ConventionInfo conventionInfo)
|
||||
{
|
||||
var genericArgument = conventionInfo.TargetProp.Type.GetGenericArguments()[0];
|
||||
|
||||
return MapLists(genericArgument, conventionInfo.SourceProp.Value);
|
||||
}
|
||||
|
||||
private static object MapLists(Type targetType, object sourceValue)
|
||||
{
|
||||
if (targetType.IsValueType || targetType == typeof(string))
|
||||
{
|
||||
return sourceValue;
|
||||
}
|
||||
|
||||
var listType = typeof(List<>).MakeGenericType(targetType);
|
||||
var addMethod = listType.GetMethod("Add");
|
||||
|
||||
var result = Activator.CreateInstance(listType);
|
||||
|
||||
foreach (var sourceItem in (IEnumerable)sourceValue)
|
||||
{
|
||||
var e = Activator.CreateInstance(targetType).InjectFrom<CloneInjection>(sourceItem);
|
||||
addMethod.Invoke(result, new[] { e });
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Common.Reflection;
|
||||
|
||||
namespace NzbDrone.Api.Mapping
|
||||
{
|
||||
public static class MappingValidation
|
||||
{
|
||||
public static void ValidateMapping(Type modelType, Type resourceType)
|
||||
{
|
||||
var errors = modelType.GetSimpleProperties().Where(c=>!c.GetGetMethod().IsStatic).Select(p => GetError(resourceType, p)).Where(c => c != null).ToList();
|
||||
|
||||
if (errors.Any())
|
||||
{
|
||||
throw new ResourceMappingException(errors);
|
||||
}
|
||||
|
||||
PrintExtraProperties(modelType, resourceType);
|
||||
}
|
||||
|
||||
private static void PrintExtraProperties(Type modelType, Type resourceType)
|
||||
{
|
||||
var resourceBaseProperties = typeof(RestResource).GetProperties().Select(c => c.Name);
|
||||
var resourceProperties = resourceType.GetProperties().Select(c => c.Name).Except(resourceBaseProperties);
|
||||
var modelProperties = modelType.GetProperties().Select(c => c.Name);
|
||||
|
||||
var extra = resourceProperties.Except(modelProperties);
|
||||
|
||||
foreach (var extraProp in extra)
|
||||
{
|
||||
Console.WriteLine("Extra: [{0}]", extraProp);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetError(Type resourceType, PropertyInfo modelProperty)
|
||||
{
|
||||
var resourceProperty = resourceType.GetProperties().FirstOrDefault(c => c.Name == modelProperty.Name);
|
||||
|
||||
if (resourceProperty == null)
|
||||
{
|
||||
return string.Format("public {0} {1} {{ get; set; }}", modelProperty.PropertyType.Name, modelProperty.Name);
|
||||
}
|
||||
|
||||
if (resourceProperty.PropertyType != modelProperty.PropertyType && !typeof(RestResource).IsAssignableFrom(resourceProperty.PropertyType))
|
||||
{
|
||||
return string.Format("Expected {0}.{1} to have type of {2} but found {3}", resourceType.Name, resourceProperty.Name, modelProperty.PropertyType, resourceProperty.PropertyType);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Api.Mapping
|
||||
{
|
||||
public class ResourceMappingException : ApplicationException
|
||||
{
|
||||
public ResourceMappingException(IEnumerable<string> error)
|
||||
: base(Environment.NewLine + string.Join(Environment.NewLine, error.OrderBy(c => c)))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.Mapping
|
||||
{
|
||||
public static class ValueInjectorExtensions
|
||||
{
|
||||
public static TTarget InjectTo<TTarget>(this object source) where TTarget : new()
|
||||
{
|
||||
if (source == null) return default(TTarget);
|
||||
|
||||
var targetType = typeof(TTarget);
|
||||
|
||||
if (targetType.IsGenericType &&
|
||||
targetType.GetGenericTypeDefinition() != null &&
|
||||
targetType.GetGenericTypeDefinition().GetInterfaces().Contains(typeof(IEnumerable)) &&
|
||||
source.GetType().IsGenericType &&
|
||||
source.GetType().GetGenericTypeDefinition() != null &&
|
||||
source.GetType().GetGenericTypeDefinition().GetInterfaces().Contains(typeof(IEnumerable)))
|
||||
{
|
||||
var result = new TTarget();
|
||||
|
||||
var listSubType = targetType.GetGenericArguments()[0];
|
||||
var listType = typeof(List<>).MakeGenericType(listSubType);
|
||||
var addMethod = listType.GetMethod("Add");
|
||||
|
||||
foreach (var sourceItem in (IEnumerable)source)
|
||||
{
|
||||
var e = Activator.CreateInstance(listSubType).InjectFrom<CloneInjection>(sourceItem);
|
||||
addMethod.Invoke(result, new[] { e });
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return (TTarget)new TTarget().InjectFrom<CloneInjection>(source);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using NzbDrone.Core.Metadata;
|
||||
using System;
|
||||
using NzbDrone.Core.Metadata;
|
||||
|
||||
namespace NzbDrone.Api.Metadata
|
||||
{
|
||||
|
@ -9,6 +10,20 @@ namespace NzbDrone.Api.Metadata
|
|||
{
|
||||
}
|
||||
|
||||
protected override void MapToResource(MetadataResource resource, MetadataDefinition definition)
|
||||
{
|
||||
base.MapToResource(resource, definition);
|
||||
|
||||
resource.Enable = definition.Enable;
|
||||
}
|
||||
|
||||
protected override void MapToModel(MetadataDefinition definition, MetadataResource resource)
|
||||
{
|
||||
base.MapToModel(definition, resource);
|
||||
|
||||
definition.Enable = resource.Enable;
|
||||
}
|
||||
|
||||
protected override void Validate(MetadataDefinition definition, bool includeWarnings)
|
||||
{
|
||||
if (!definition.Enable) return;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using NzbDrone.Core.Notifications;
|
||||
using System;
|
||||
using NzbDrone.Core.Notifications;
|
||||
|
||||
namespace NzbDrone.Api.Notifications
|
||||
{
|
||||
|
@ -9,6 +10,36 @@ namespace NzbDrone.Api.Notifications
|
|||
{
|
||||
}
|
||||
|
||||
protected override void MapToResource(NotificationResource resource, NotificationDefinition definition)
|
||||
{
|
||||
base.MapToResource(resource, definition);
|
||||
|
||||
resource.OnGrab = definition.OnGrab;
|
||||
resource.OnDownload = definition.OnDownload;
|
||||
resource.OnUpgrade = definition.OnUpgrade;
|
||||
resource.OnRename = definition.OnRename;
|
||||
resource.SupportsOnGrab = definition.SupportsOnGrab;
|
||||
resource.SupportsOnDownload = definition.SupportsOnDownload;
|
||||
resource.SupportsOnUpgrade = definition.SupportsOnUpgrade;
|
||||
resource.SupportsOnRename = definition.SupportsOnRename;
|
||||
resource.Tags = definition.Tags;
|
||||
}
|
||||
|
||||
protected override void MapToModel(NotificationDefinition definition, NotificationResource resource)
|
||||
{
|
||||
base.MapToModel(definition, resource);
|
||||
|
||||
definition.OnGrab = resource.OnGrab;
|
||||
definition.OnDownload = resource.OnDownload;
|
||||
definition.OnUpgrade = resource.OnUpgrade;
|
||||
definition.OnRename = resource.OnRename;
|
||||
definition.SupportsOnGrab = resource.SupportsOnGrab;
|
||||
definition.SupportsOnDownload = resource.SupportsOnDownload;
|
||||
definition.SupportsOnUpgrade = resource.SupportsOnUpgrade;
|
||||
definition.SupportsOnRename = resource.SupportsOnRename;
|
||||
definition.Tags = resource.Tags;
|
||||
}
|
||||
|
||||
protected override void Validate(NotificationDefinition definition, bool includeWarnings)
|
||||
{
|
||||
if (!definition.OnGrab && !definition.OnDownload) return;
|
||||
|
|
|
@ -4,7 +4,6 @@ namespace NzbDrone.Api.Notifications
|
|||
{
|
||||
public class NotificationResource : ProviderResource
|
||||
{
|
||||
public string Link { get; set; }
|
||||
public bool OnGrab { get; set; }
|
||||
public bool OnDownload { get; set; }
|
||||
public bool OnUpgrade { get; set; }
|
||||
|
@ -13,7 +12,6 @@ namespace NzbDrone.Api.Notifications
|
|||
public bool SupportsOnDownload { get; set; }
|
||||
public bool SupportsOnUpgrade { get; set; }
|
||||
public bool SupportsOnRename { get; set; }
|
||||
public string TestCommand { get; set; }
|
||||
public HashSet<int> Tags { get; set; }
|
||||
}
|
||||
}
|
|
@ -70,9 +70,6 @@
|
|||
<Reference Include="DDay.iCal">
|
||||
<HintPath>..\packages\DDay.iCal.1.0.2.575\lib\DDay.iCal.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Omu.ValueInjecter">
|
||||
<HintPath>..\packages\ValueInjecter.2.3.3\lib\net35\Omu.ValueInjecter.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SQLite, Version=1.0.84.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Libraries\Sqlite\System.Data.SQLite.dll</HintPath>
|
||||
|
@ -111,7 +108,6 @@
|
|||
<Compile Include="ManualImport\ManualImportResource.cs" />
|
||||
<Compile Include="Profiles\Delay\DelayProfileModule.cs" />
|
||||
<Compile Include="Profiles\Delay\DelayProfileResource.cs" />
|
||||
<Compile Include="Profiles\Delay\DelayProfileValidator.cs" />
|
||||
<Compile Include="Queue\QueueActionModule.cs" />
|
||||
<Compile Include="RemotePathMappings\RemotePathMappingModule.cs" />
|
||||
<Compile Include="RemotePathMappings\RemotePathMappingResource.cs" />
|
||||
|
@ -146,7 +142,6 @@
|
|||
<Compile Include="ErrorManagement\ErrorModel.cs" />
|
||||
<Compile Include="ErrorManagement\NzbDroneErrorPipeline.cs" />
|
||||
<Compile Include="Exceptions\InvalidApiKeyException.cs" />
|
||||
<Compile Include="Extensions\LazyExtensions.cs" />
|
||||
<Compile Include="Extensions\NancyJsonSerializer.cs" />
|
||||
<Compile Include="Extensions\Pipelines\CacheHeaderPipeline.cs" />
|
||||
<Compile Include="Extensions\Pipelines\GZipPipeline.cs" />
|
||||
|
@ -181,10 +176,6 @@
|
|||
<Compile Include="Logs\LogModule.cs" />
|
||||
<Compile Include="Logs\LogResource.cs" />
|
||||
<Compile Include="Logs\UpdateLogFileModule.cs" />
|
||||
<Compile Include="Mapping\CloneInjection.cs" />
|
||||
<Compile Include="Mapping\MappingValidation.cs" />
|
||||
<Compile Include="Mapping\ResourceMappingException.cs" />
|
||||
<Compile Include="Mapping\ValueInjectorExtensions.cs" />
|
||||
<Compile Include="MediaCovers\MediaCoverModule.cs" />
|
||||
<Compile Include="Metadata\MetadataModule.cs" />
|
||||
<Compile Include="Metadata\MetadataResource.cs" />
|
||||
|
|
|
@ -4,7 +4,6 @@ using System.Collections.Generic;
|
|||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Api.Validation;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Api.Mapping;
|
||||
|
||||
namespace NzbDrone.Api
|
||||
{
|
||||
|
@ -25,30 +24,7 @@ namespace NzbDrone.Api
|
|||
PutValidator.RuleFor(r => r.Id).ValidId();
|
||||
}
|
||||
|
||||
protected int GetNewId<TModel>(Func<TModel, TModel> function, TResource resource) where TModel : ModelBase, new()
|
||||
{
|
||||
var model = resource.InjectTo<TModel>();
|
||||
function(model);
|
||||
return model.Id;
|
||||
}
|
||||
|
||||
protected List<TResource> ToListResource<TModel>(Func<IEnumerable<TModel>> function) where TModel : class
|
||||
{
|
||||
var modelList = function();
|
||||
return ToListResource(modelList);
|
||||
}
|
||||
|
||||
protected virtual List<TResource> ToListResource<TModel>(IEnumerable<TModel> modelList) where TModel : class
|
||||
{
|
||||
return modelList.Select(ToResource).ToList();
|
||||
}
|
||||
|
||||
protected virtual TResource ToResource<TModel>(TModel model) where TModel : class
|
||||
{
|
||||
return model.InjectTo<TResource>();
|
||||
}
|
||||
|
||||
protected PagingResource<TResource> ApplyToPage<TModel>(Func<PagingSpec<TModel>, PagingSpec<TModel>> function, PagingSpec<TModel> pagingSpec) where TModel : ModelBase, new()
|
||||
protected PagingResource<TResource> ApplyToPage<TModel>(Func<PagingSpec<TModel>, PagingSpec<TModel>> function, PagingSpec<TModel> pagingSpec, Converter<TModel, TResource> mapper)
|
||||
{
|
||||
pagingSpec = function(pagingSpec);
|
||||
|
||||
|
@ -59,7 +35,7 @@ namespace NzbDrone.Api
|
|||
SortDirection = pagingSpec.SortDirection,
|
||||
SortKey = pagingSpec.SortKey,
|
||||
TotalRecords = pagingSpec.TotalRecords,
|
||||
Records = ToListResource(pagingSpec.Records)
|
||||
Records = pagingSpec.Records.ConvertAll(mapper)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace NzbDrone.Api
|
|||
{
|
||||
public abstract class NzbDroneRestModuleWithSignalR<TResource, TModel> : NzbDroneRestModule<TResource>, IHandle<ModelEvent<TModel>>
|
||||
where TResource : RestResource, new()
|
||||
where TModel : ModelBase
|
||||
where TModel : ModelBase, new()
|
||||
{
|
||||
private readonly IBroadcastSignalRMessage _signalRBroadcaster;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ using NzbDrone.Core.Datastore;
|
|||
|
||||
namespace NzbDrone.Api
|
||||
{
|
||||
public class PagingResource<TModel>
|
||||
public class PagingResource<TResource>
|
||||
{
|
||||
public int Page { get; set; }
|
||||
public int PageSize { get; set; }
|
||||
|
@ -12,6 +12,20 @@ namespace NzbDrone.Api
|
|||
public string FilterKey { get; set; }
|
||||
public string FilterValue { get; set; }
|
||||
public int TotalRecords { get; set; }
|
||||
public List<TModel> Records { get; set; }
|
||||
public List<TResource> Records { get; set; }
|
||||
}
|
||||
|
||||
public static class PagingResourceMapper
|
||||
{
|
||||
public static PagingSpec<TModel> MapToPagingSpec<TResource, TModel>(this PagingResource<TResource> pagingSpec)
|
||||
{
|
||||
return new PagingSpec<TModel>
|
||||
{
|
||||
Page = pagingSpec.Page,
|
||||
PageSize = pagingSpec.PageSize,
|
||||
SortKey = pagingSpec.SortKey,
|
||||
SortDirection = pagingSpec.SortDirection,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Api.Episodes;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Core.Parser;
|
||||
|
||||
namespace NzbDrone.Api.Parse
|
||||
{
|
||||
|
@ -16,7 +17,7 @@ namespace NzbDrone.Api.Parse
|
|||
|
||||
private ParseResource Parse()
|
||||
{
|
||||
var title = Request.Query.Title.Value;
|
||||
var title = Request.Query.Title.Value as string;
|
||||
var parsedEpisodeInfo = Parser.ParseTitle(title);
|
||||
|
||||
if (parsedEpisodeInfo == null)
|
||||
|
@ -26,24 +27,24 @@ namespace NzbDrone.Api.Parse
|
|||
|
||||
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0, 0);
|
||||
|
||||
if (remoteEpisode == null)
|
||||
if (remoteEpisode != null)
|
||||
{
|
||||
remoteEpisode = new RemoteEpisode
|
||||
return new ParseResource
|
||||
{
|
||||
ParsedEpisodeInfo = parsedEpisodeInfo
|
||||
Title = title,
|
||||
ParsedEpisodeInfo = remoteEpisode.ParsedEpisodeInfo,
|
||||
Series = remoteEpisode.Series.ToResource(),
|
||||
Episodes = remoteEpisode.Episodes.ToResource()
|
||||
};
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ParseResource
|
||||
{
|
||||
Title = title,
|
||||
ParsedEpisodeInfo = parsedEpisodeInfo
|
||||
};
|
||||
}
|
||||
|
||||
var resource = ToResource(remoteEpisode);
|
||||
resource.Title = title;
|
||||
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Api.Validation;
|
||||
using NzbDrone.Core.Profiles.Delay;
|
||||
|
@ -26,12 +26,21 @@ namespace NzbDrone.Api.Profiles.Delay
|
|||
SharedValidator.RuleFor(d => d.Tags).SetValidator(tagInUseValidator);
|
||||
SharedValidator.RuleFor(d => d.UsenetDelay).GreaterThanOrEqualTo(0);
|
||||
SharedValidator.RuleFor(d => d.TorrentDelay).GreaterThanOrEqualTo(0);
|
||||
SharedValidator.RuleFor(d => d.Id).SetValidator(new DelayProfileValidator());
|
||||
|
||||
SharedValidator.Custom(delayProfile =>
|
||||
{
|
||||
if (!delayProfile.EnableUsenet && !delayProfile.EnableTorrent)
|
||||
{
|
||||
return new ValidationFailure("", "Either Usenet or Torrent should be enabled");
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private int Create(DelayProfileResource resource)
|
||||
{
|
||||
var model = resource.InjectTo<DelayProfile>();
|
||||
var model = resource.ToModel();
|
||||
model = _delayProfileService.Add(model);
|
||||
|
||||
return model.Id;
|
||||
|
@ -49,17 +58,18 @@ namespace NzbDrone.Api.Profiles.Delay
|
|||
|
||||
private void Update(DelayProfileResource resource)
|
||||
{
|
||||
GetNewId<DelayProfile>(_delayProfileService.Update, resource);
|
||||
var model = resource.ToModel();
|
||||
_delayProfileService.Update(model);
|
||||
}
|
||||
|
||||
private DelayProfileResource GetById(int id)
|
||||
{
|
||||
return _delayProfileService.Get(id).InjectTo<DelayProfileResource>();
|
||||
return _delayProfileService.Get(id).ToResource();
|
||||
}
|
||||
|
||||
private List<DelayProfileResource> GetAll()
|
||||
{
|
||||
return _delayProfileService.All().InjectTo<List<DelayProfileResource>>();
|
||||
return _delayProfileService.All().ToResource();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Profiles.Delay;
|
||||
|
||||
namespace NzbDrone.Api.Profiles.Delay
|
||||
{
|
||||
|
@ -14,4 +16,48 @@ namespace NzbDrone.Api.Profiles.Delay
|
|||
public int Order { get; set; }
|
||||
public HashSet<int> Tags { get; set; }
|
||||
}
|
||||
|
||||
public static class DelayProfileResourceMapper
|
||||
{
|
||||
public static DelayProfileResource ToResource(this DelayProfile model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new DelayProfileResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
EnableUsenet = model.EnableUsenet,
|
||||
EnableTorrent = model.EnableTorrent,
|
||||
PreferredProtocol = model.PreferredProtocol,
|
||||
UsenetDelay = model.UsenetDelay,
|
||||
TorrentDelay = model.TorrentDelay,
|
||||
Order = model.Order,
|
||||
Tags = new HashSet<int>(model.Tags)
|
||||
};
|
||||
}
|
||||
|
||||
public static DelayProfile ToModel(this DelayProfileResource resource)
|
||||
{
|
||||
if (resource == null) return null;
|
||||
|
||||
return new DelayProfile
|
||||
{
|
||||
Id = resource.Id,
|
||||
|
||||
EnableUsenet = resource.EnableUsenet,
|
||||
EnableTorrent = resource.EnableTorrent,
|
||||
PreferredProtocol = resource.PreferredProtocol,
|
||||
UsenetDelay = resource.UsenetDelay,
|
||||
TorrentDelay = resource.TorrentDelay,
|
||||
Order = resource.Order,
|
||||
Tags = new HashSet<int>(resource.Tags)
|
||||
};
|
||||
}
|
||||
|
||||
public static List<DelayProfileResource> ToResource(this IEnumerable<DelayProfile> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
using FluentValidation.Validators;
|
||||
using NzbDrone.Core.Profiles.Delay;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.Profiles.Delay
|
||||
{
|
||||
public class DelayProfileValidator : PropertyValidator
|
||||
{
|
||||
public DelayProfileValidator()
|
||||
: base("Usenet or Torrent must be enabled")
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool IsValid(PropertyValidatorContext context)
|
||||
{
|
||||
var delayProfile = new DelayProfile();
|
||||
delayProfile.InjectFrom(context.ParentContext.InstanceToValidate);
|
||||
|
||||
if (!delayProfile.EnableUsenet && !delayProfile.EnableTorrent)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ namespace NzbDrone.Api.Profiles.Languages
|
|||
public class LanguageResource : RestResource
|
||||
{
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)]
|
||||
public int Id { get; set; }
|
||||
public new int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string NameLower { get { return Name.ToLowerInvariant(); } }
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Core.Profiles;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
@ -28,9 +27,9 @@ namespace NzbDrone.Api.Profiles
|
|||
|
||||
private int Create(ProfileResource resource)
|
||||
{
|
||||
var model = resource.InjectTo<Profile>();
|
||||
model = _profileService.Add(model);
|
||||
return model.Id;
|
||||
var model = resource.ToModel();
|
||||
|
||||
return _profileService.Add(model).Id;
|
||||
}
|
||||
|
||||
private void DeleteProfile(int id)
|
||||
|
@ -40,26 +39,19 @@ namespace NzbDrone.Api.Profiles
|
|||
|
||||
private void Update(ProfileResource resource)
|
||||
{
|
||||
var model = _profileService.Get(resource.Id);
|
||||
|
||||
model.Name = resource.Name;
|
||||
model.Cutoff = (Quality)resource.Cutoff.Id;
|
||||
model.Items = resource.Items.InjectTo<List<ProfileQualityItem>>();
|
||||
model.Language = resource.Language;
|
||||
var model = resource.ToModel();
|
||||
|
||||
_profileService.Update(model);
|
||||
}
|
||||
|
||||
private ProfileResource GetById(int id)
|
||||
{
|
||||
return _profileService.Get(id).InjectTo<ProfileResource>();
|
||||
return _profileService.Get(id).ToResource();
|
||||
}
|
||||
|
||||
private List<ProfileResource> GetAll()
|
||||
{
|
||||
var profiles = _profileService.All().InjectTo<List<ProfileResource>>();
|
||||
|
||||
return profiles;
|
||||
return _profileService.All().ToResource();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Profiles;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
namespace NzbDrone.Api.Profiles
|
||||
|
@ -19,4 +21,64 @@ namespace NzbDrone.Api.Profiles
|
|||
public Quality Quality { get; set; }
|
||||
public bool Allowed { get; set; }
|
||||
}
|
||||
|
||||
public static class ProfileResourceMapper
|
||||
{
|
||||
public static ProfileResource ToResource(this Profile model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new ProfileResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
Name = model.Name,
|
||||
Cutoff = model.Cutoff,
|
||||
Items = model.Items.ConvertAll(ToResource),
|
||||
Language = model.Language
|
||||
};
|
||||
}
|
||||
|
||||
public static ProfileQualityItemResource ToResource(this ProfileQualityItem model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new ProfileQualityItemResource
|
||||
{
|
||||
Quality = model.Quality,
|
||||
Allowed = model.Allowed
|
||||
};
|
||||
}
|
||||
|
||||
public static Profile ToModel(this ProfileResource resource)
|
||||
{
|
||||
if (resource == null) return null;
|
||||
|
||||
return new Profile
|
||||
{
|
||||
Id = resource.Id,
|
||||
|
||||
Name = resource.Name,
|
||||
Cutoff = (Quality)resource.Cutoff.Id,
|
||||
Items = resource.Items.ConvertAll(ToModel),
|
||||
Language = resource.Language
|
||||
};
|
||||
}
|
||||
|
||||
public static ProfileQualityItem ToModel(this ProfileQualityItemResource resource)
|
||||
{
|
||||
if (resource == null) return null;
|
||||
|
||||
return new ProfileQualityItem
|
||||
{
|
||||
Quality = (Quality)resource.Quality.Id,
|
||||
Allowed = resource.Allowed
|
||||
};
|
||||
}
|
||||
|
||||
public static List<ProfileResource> ToResource(this IEnumerable<Profile> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Profiles;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
@ -31,7 +30,7 @@ namespace NzbDrone.Api.Profiles
|
|||
profile.Items = items;
|
||||
profile.Language = Language.English;
|
||||
|
||||
return new List<ProfileResource> { profile.InjectTo<ProfileResource>() };
|
||||
return new List<ProfileResource> { profile.ToResource() };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,11 +6,9 @@ using FluentValidation.Results;
|
|||
using Nancy;
|
||||
using NzbDrone.Api.ClientSchema;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Common.Reflection;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
using Omu.ValueInjecter;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NzbDrone.Api
|
||||
|
@ -48,9 +46,10 @@ namespace NzbDrone.Api
|
|||
private TProviderResource GetProviderById(int id)
|
||||
{
|
||||
var definition = _providerFactory.Get(id);
|
||||
var resource = definition.InjectTo<TProviderResource>();
|
||||
_providerFactory.SetProviderCharacteristics(definition);
|
||||
|
||||
resource.InjectFrom(_providerFactory.GetProviderCharacteristics(_providerFactory.GetInstance(definition), definition));
|
||||
var resource = new TProviderResource();
|
||||
MapToResource(resource, definition);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
@ -63,10 +62,10 @@ namespace NzbDrone.Api
|
|||
|
||||
foreach (var definition in providerDefinitions)
|
||||
{
|
||||
_providerFactory.SetProviderCharacteristics(definition);
|
||||
|
||||
var providerResource = new TProviderResource();
|
||||
providerResource.InjectFrom(definition);
|
||||
providerResource.InjectFrom(_providerFactory.GetProviderCharacteristics(_providerFactory.GetInstance(definition), definition));
|
||||
providerResource.Fields = SchemaBuilder.ToSchema(definition.Settings);
|
||||
MapToResource(providerResource, definition);
|
||||
|
||||
result.Add(providerResource);
|
||||
}
|
||||
|
@ -99,15 +98,8 @@ namespace NzbDrone.Api
|
|||
{
|
||||
var definition = new TProviderDefinition();
|
||||
|
||||
definition.InjectFrom(providerResource);
|
||||
MapToModel(definition, providerResource);
|
||||
|
||||
var preset = _providerFactory.GetPresetDefinitions(definition)
|
||||
.Where(v => v.Name == definition.Name)
|
||||
.Select(v => v.Settings)
|
||||
.FirstOrDefault();
|
||||
|
||||
var configContract = ReflectionExtensions.CoreAssembly.FindTypeByName(definition.ConfigContract);
|
||||
definition.Settings = (IProviderConfig)SchemaBuilder.ReadFormSchema(providerResource.Fields, configContract, preset);
|
||||
if (validate)
|
||||
{
|
||||
Validate(definition, includeWarnings);
|
||||
|
@ -116,6 +108,37 @@ namespace NzbDrone.Api
|
|||
return definition;
|
||||
}
|
||||
|
||||
protected virtual void MapToResource(TProviderResource resource, TProviderDefinition definition)
|
||||
{
|
||||
resource.Id = definition.Id;
|
||||
|
||||
resource.Name = definition.Name;
|
||||
resource.ImplementationName = definition.ImplementationName;
|
||||
resource.Implementation = definition.Implementation;
|
||||
resource.ConfigContract = definition.ConfigContract;
|
||||
resource.Message = definition.Message;
|
||||
|
||||
resource.Fields = SchemaBuilder.ToSchema(definition.Settings);
|
||||
|
||||
resource.InfoLink = string.Format("https://github.com/Sonarr/Sonarr/wiki/Supported-{0}#{1}",
|
||||
typeof(TProviderResource).Name.Replace("Resource", "s"),
|
||||
definition.Implementation.ToLower());
|
||||
}
|
||||
|
||||
protected virtual void MapToModel(TProviderDefinition definition, TProviderResource resource)
|
||||
{
|
||||
definition.Id = resource.Id;
|
||||
|
||||
definition.Name = resource.Name;
|
||||
definition.ImplementationName = resource.ImplementationName;
|
||||
definition.Implementation = resource.Implementation;
|
||||
definition.ConfigContract = resource.ConfigContract;
|
||||
definition.Message = resource.Message;
|
||||
|
||||
var configContract = ReflectionExtensions.CoreAssembly.FindTypeByName(definition.ConfigContract);
|
||||
definition.Settings = (IProviderConfig)SchemaBuilder.ReadFromSchema(resource.Fields, configContract);
|
||||
}
|
||||
|
||||
private void DeleteProvider(int id)
|
||||
{
|
||||
_providerFactory.Delete(id);
|
||||
|
@ -130,19 +153,14 @@ namespace NzbDrone.Api
|
|||
foreach (var providerDefinition in defaultDefinitions)
|
||||
{
|
||||
var providerResource = new TProviderResource();
|
||||
providerResource.InjectFrom(providerDefinition);
|
||||
providerResource.Fields = SchemaBuilder.ToSchema(providerDefinition.Settings);
|
||||
providerResource.InfoLink = string.Format("https://github.com/NzbDrone/NzbDrone/wiki/Supported-{0}#{1}",
|
||||
typeof(TProviderResource).Name.Replace("Resource", "s"),
|
||||
providerDefinition.Implementation.ToLower());
|
||||
MapToResource(providerResource, providerDefinition);
|
||||
|
||||
var presetDefinitions = _providerFactory.GetPresetDefinitions(providerDefinition);
|
||||
|
||||
providerResource.Presets = presetDefinitions.Select(v =>
|
||||
{
|
||||
var presetResource = new TProviderResource();
|
||||
presetResource.InjectFrom(v);
|
||||
presetResource.Fields = SchemaBuilder.ToSchema(v.Settings);
|
||||
MapToResource(presetResource, v);
|
||||
|
||||
return presetResource as ProviderResource;
|
||||
}).ToList();
|
||||
|
@ -167,7 +185,7 @@ namespace NzbDrone.Api
|
|||
|
||||
private Response ConnectData(string stage, TProviderResource providerResource)
|
||||
{
|
||||
TProviderDefinition providerDefinition = GetDefinition(providerResource, true, false);
|
||||
var providerDefinition = GetDefinition(providerResource, true, false);
|
||||
|
||||
if (!providerDefinition.Enable) return "{}";
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Api.Mapping;
|
||||
|
||||
namespace NzbDrone.Api.Qualities
|
||||
{
|
||||
|
@ -21,18 +20,18 @@ namespace NzbDrone.Api.Qualities
|
|||
|
||||
private void Update(QualityDefinitionResource resource)
|
||||
{
|
||||
var model = resource.InjectTo<QualityDefinition>();
|
||||
var model = resource.ToModel();
|
||||
_qualityDefinitionService.Update(model);
|
||||
}
|
||||
|
||||
private QualityDefinitionResource GetById(int id)
|
||||
{
|
||||
return _qualityDefinitionService.GetById(id).InjectTo<QualityDefinitionResource>();
|
||||
return _qualityDefinitionService.GetById(id).ToResource();
|
||||
}
|
||||
|
||||
private List<QualityDefinitionResource> GetAll()
|
||||
{
|
||||
return ToListResource(_qualityDefinitionService.All);
|
||||
return _qualityDefinitionService.All().ToResource();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
|
@ -15,4 +17,50 @@ namespace NzbDrone.Api.Qualities
|
|||
public double? MinSize { get; set; }
|
||||
public double? MaxSize { get; set; }
|
||||
}
|
||||
|
||||
public static class QualityDefinitionResourceMapper
|
||||
{
|
||||
public static QualityDefinitionResource ToResource(this QualityDefinition model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new QualityDefinitionResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
Quality = model.Quality,
|
||||
|
||||
Title = model.Title,
|
||||
|
||||
Weight = model.Weight,
|
||||
|
||||
MinSize = model.MinSize,
|
||||
MaxSize = model.MaxSize
|
||||
};
|
||||
}
|
||||
|
||||
public static QualityDefinition ToModel(this QualityDefinitionResource resource)
|
||||
{
|
||||
if (resource == null) return null;
|
||||
|
||||
return new QualityDefinition
|
||||
{
|
||||
Id = resource.Id,
|
||||
|
||||
Quality = resource.Quality,
|
||||
|
||||
Title = resource.Title,
|
||||
|
||||
Weight = resource.Weight,
|
||||
|
||||
MinSize = resource.MinSize,
|
||||
MaxSize = resource.MaxSize
|
||||
};
|
||||
}
|
||||
|
||||
public static List<QualityDefinitionResource> ToResource(this IEnumerable<QualityDefinition> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ namespace NzbDrone.Api.Queue
|
|||
|
||||
private List<QueueResource> GetQueue()
|
||||
{
|
||||
return ToListResource(GetQueueItems);
|
||||
return GetQueueItems().ToResource();
|
||||
}
|
||||
|
||||
private IEnumerable<Core.Queue.Queue> GetQueueItems()
|
||||
|
|
|
@ -6,6 +6,7 @@ using NzbDrone.Api.Series;
|
|||
using NzbDrone.Api.Episodes;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Api.Queue
|
||||
{
|
||||
|
@ -25,4 +26,36 @@ namespace NzbDrone.Api.Queue
|
|||
public string DownloadId { get; set; }
|
||||
public DownloadProtocol Protocol { get; set; }
|
||||
}
|
||||
|
||||
public static class QueueResourceMapper
|
||||
{
|
||||
public static QueueResource ToResource(this Core.Queue.Queue model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new QueueResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
Series = model.Series.ToResource(),
|
||||
Episode = model.Episode.ToResource(),
|
||||
Quality = model.Quality,
|
||||
Size = model.Size,
|
||||
Title = model.Title,
|
||||
Sizeleft = model.Sizeleft,
|
||||
Timeleft = model.Timeleft,
|
||||
EstimatedCompletionTime = model.EstimatedCompletionTime,
|
||||
Status = model.Status,
|
||||
TrackedDownloadStatus = model.TrackedDownloadStatus,
|
||||
StatusMessages = model.StatusMessages,
|
||||
DownloadId = model.DownloadId,
|
||||
Protocol = model.Protocol
|
||||
};
|
||||
}
|
||||
|
||||
public static List<QueueResource> ToResource(this IEnumerable<Core.Queue.Queue> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Core.RemotePathMappings;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.RemotePathMappings
|
||||
{
|
||||
|
@ -39,17 +37,19 @@ namespace NzbDrone.Api.RemotePathMappings
|
|||
|
||||
private RemotePathMappingResource GetMappingById(int id)
|
||||
{
|
||||
return _remotePathMappingService.Get(id).InjectTo<RemotePathMappingResource>();
|
||||
return _remotePathMappingService.Get(id).ToResource();
|
||||
}
|
||||
|
||||
private int CreateMapping(RemotePathMappingResource rootFolderResource)
|
||||
private int CreateMapping(RemotePathMappingResource resource)
|
||||
{
|
||||
return GetNewId<RemotePathMapping>(_remotePathMappingService.Add, rootFolderResource);
|
||||
var model = resource.ToModel();
|
||||
|
||||
return _remotePathMappingService.Add(model).Id;
|
||||
}
|
||||
|
||||
private List<RemotePathMappingResource> GetMappings()
|
||||
{
|
||||
return ToListResource(_remotePathMappingService.All);
|
||||
return _remotePathMappingService.All().ToResource();
|
||||
}
|
||||
|
||||
private void DeleteMapping(int id)
|
||||
|
@ -59,9 +59,7 @@ namespace NzbDrone.Api.RemotePathMappings
|
|||
|
||||
private void UpdateMapping(RemotePathMappingResource resource)
|
||||
{
|
||||
var mapping = _remotePathMappingService.Get(resource.Id);
|
||||
|
||||
mapping.InjectFrom(resource);
|
||||
var mapping = resource.ToModel();
|
||||
|
||||
_remotePathMappingService.Update(mapping);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.RemotePathMappings;
|
||||
|
||||
namespace NzbDrone.Api.RemotePathMappings
|
||||
{
|
||||
|
@ -9,4 +12,40 @@ namespace NzbDrone.Api.RemotePathMappings
|
|||
public string RemotePath { get; set; }
|
||||
public string LocalPath { get; set; }
|
||||
}
|
||||
|
||||
public static class RemotePathMappingResourceMapper
|
||||
{
|
||||
public static RemotePathMappingResource ToResource(this RemotePathMapping model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new RemotePathMappingResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
Host = model.Host,
|
||||
RemotePath = model.RemotePath,
|
||||
LocalPath = model.LocalPath
|
||||
};
|
||||
}
|
||||
|
||||
public static RemotePathMapping ToModel(this RemotePathMappingResource resource)
|
||||
{
|
||||
if (resource == null) return null;
|
||||
|
||||
return new RemotePathMapping
|
||||
{
|
||||
Id = resource.Id,
|
||||
|
||||
Host = resource.Host,
|
||||
RemotePath = resource.RemotePath,
|
||||
LocalPath = resource.LocalPath
|
||||
};
|
||||
}
|
||||
|
||||
public static List<RemotePathMappingResource> ToResource(this IEnumerable<RemotePathMapping> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Restrictions;
|
||||
|
||||
|
@ -16,11 +15,11 @@ namespace NzbDrone.Api.Restrictions
|
|||
{
|
||||
_restrictionService = restrictionService;
|
||||
|
||||
GetResourceById = Get;
|
||||
GetResourceAll = GetAll;
|
||||
CreateResource = Create;
|
||||
UpdateResource = Update;
|
||||
DeleteResource = Delete;
|
||||
GetResourceById = GetRestriction;
|
||||
GetResourceAll = GetAllRestrictions;
|
||||
CreateResource = CreateRestriction;
|
||||
UpdateResource = UpdateRestriction;
|
||||
DeleteResource = DeleteRestriction;
|
||||
|
||||
SharedValidator.Custom(restriction =>
|
||||
{
|
||||
|
@ -33,27 +32,27 @@ namespace NzbDrone.Api.Restrictions
|
|||
});
|
||||
}
|
||||
|
||||
private RestrictionResource Get(int id)
|
||||
private RestrictionResource GetRestriction(int id)
|
||||
{
|
||||
return _restrictionService.Get(id).InjectTo<RestrictionResource>();
|
||||
return _restrictionService.Get(id).ToResource();
|
||||
}
|
||||
|
||||
private List<RestrictionResource> GetAll()
|
||||
private List<RestrictionResource> GetAllRestrictions()
|
||||
{
|
||||
return ToListResource(_restrictionService.All);
|
||||
return _restrictionService.All().ToResource();
|
||||
}
|
||||
|
||||
private int Create(RestrictionResource resource)
|
||||
private int CreateRestriction(RestrictionResource resource)
|
||||
{
|
||||
return _restrictionService.Add(resource.InjectTo<Restriction>()).Id;
|
||||
return _restrictionService.Add(resource.ToModel()).Id;
|
||||
}
|
||||
|
||||
private void Update(RestrictionResource resource)
|
||||
private void UpdateRestriction(RestrictionResource resource)
|
||||
{
|
||||
_restrictionService.Update(resource.InjectTo<Restriction>());
|
||||
_restrictionService.Update(resource.ToModel());
|
||||
}
|
||||
|
||||
private void Delete(int id)
|
||||
private void DeleteRestriction(int id)
|
||||
{
|
||||
_restrictionService.Delete(id);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Restrictions;
|
||||
|
||||
namespace NzbDrone.Api.Restrictions
|
||||
{
|
||||
|
@ -16,4 +18,42 @@ namespace NzbDrone.Api.Restrictions
|
|||
Tags = new HashSet<int>();
|
||||
}
|
||||
}
|
||||
|
||||
public static class RestrictionResourceMapper
|
||||
{
|
||||
public static RestrictionResource ToResource(this Restriction model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new RestrictionResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
Required = model.Required,
|
||||
Preferred = model.Preferred,
|
||||
Ignored = model.Ignored,
|
||||
Tags = new HashSet<int>(model.Tags)
|
||||
};
|
||||
}
|
||||
|
||||
public static Restriction ToModel(this RestrictionResource resource)
|
||||
{
|
||||
if (resource == null) return null;
|
||||
|
||||
return new Restriction
|
||||
{
|
||||
Id = resource.Id,
|
||||
|
||||
Required = resource.Required,
|
||||
Preferred = resource.Preferred,
|
||||
Ignored = resource.Ignored,
|
||||
Tags = new HashSet<int>(resource.Tags)
|
||||
};
|
||||
}
|
||||
|
||||
public static List<RestrictionResource> ToResource(this IEnumerable<Restriction> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
using NzbDrone.SignalR;
|
||||
|
||||
|
@ -41,17 +40,19 @@ namespace NzbDrone.Api.RootFolders
|
|||
|
||||
private RootFolderResource GetRootFolder(int id)
|
||||
{
|
||||
return _rootFolderService.Get(id).InjectTo<RootFolderResource>();
|
||||
return _rootFolderService.Get(id).ToResource();
|
||||
}
|
||||
|
||||
private int CreateRootFolder(RootFolderResource rootFolderResource)
|
||||
{
|
||||
return GetNewId<RootFolder>(_rootFolderService.Add, rootFolderResource);
|
||||
var model = rootFolderResource.ToModel();
|
||||
|
||||
return _rootFolderService.Add(model).Id;
|
||||
}
|
||||
|
||||
private List<RootFolderResource> GetRootFolders()
|
||||
{
|
||||
return ToListResource(_rootFolderService.AllWithUnmappedFolders);
|
||||
return _rootFolderService.AllWithUnmappedFolders().ToResource();
|
||||
}
|
||||
|
||||
private void DeleteFolder(int id)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
|
||||
|
@ -12,4 +13,40 @@ namespace NzbDrone.Api.RootFolders
|
|||
|
||||
public List<UnmappedFolder> UnmappedFolders { get; set; }
|
||||
}
|
||||
|
||||
public static class RootFolderResourceMapper
|
||||
{
|
||||
public static RootFolderResource ToResource(this RootFolder model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new RootFolderResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
Path = model.Path,
|
||||
FreeSpace = model.FreeSpace,
|
||||
UnmappedFolders = model.UnmappedFolders
|
||||
};
|
||||
}
|
||||
|
||||
public static RootFolder ToModel(this RootFolderResource resource)
|
||||
{
|
||||
if (resource == null) return null;
|
||||
|
||||
return new RootFolder
|
||||
{
|
||||
Id = resource.Id,
|
||||
|
||||
Path = resource.Path,
|
||||
//FreeSpace
|
||||
//UnmappedFolders
|
||||
};
|
||||
}
|
||||
|
||||
public static List<RootFolderResource> ToResource(this IEnumerable<RootFolder> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using Nancy;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Api.SeasonPass
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace NzbDrone.Api.Series
|
|||
public class AlternateTitleResource
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public int SeasonNumber { get; set; }
|
||||
public int SceneSeasonNumber { get; set; }
|
||||
public int? SeasonNumber { get; set; }
|
||||
public int? SceneSeasonNumber { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
namespace NzbDrone.Api.Series
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Tv;
|
||||
namespace NzbDrone.Api.Series
|
||||
{
|
||||
public class SeasonResource
|
||||
{
|
||||
|
@ -6,4 +9,39 @@
|
|||
public bool Monitored { get; set; }
|
||||
public SeasonStatisticsResource Statistics { get; set; }
|
||||
}
|
||||
|
||||
public static class SeasonResourceMapper
|
||||
{
|
||||
public static SeasonResource ToResource(this Season model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new SeasonResource
|
||||
{
|
||||
SeasonNumber = model.SeasonNumber,
|
||||
Monitored = model.Monitored
|
||||
};
|
||||
}
|
||||
|
||||
public static Season ToModel(this SeasonResource resource)
|
||||
{
|
||||
if (resource == null) return null;
|
||||
|
||||
return new Season
|
||||
{
|
||||
SeasonNumber = resource.SeasonNumber,
|
||||
Monitored = resource.Monitored
|
||||
};
|
||||
}
|
||||
|
||||
public static List<SeasonResource> ToResource(this IEnumerable<Season> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
|
||||
public static List<Season> ToModel(this IEnumerable<SeasonResource> resources)
|
||||
{
|
||||
return resources.Select(ToModel).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using NzbDrone.Core.SeriesStats;
|
||||
|
||||
namespace NzbDrone.Api.Series
|
||||
{
|
||||
|
@ -20,6 +21,23 @@ namespace NzbDrone.Api.Series
|
|||
return (decimal)EpisodeFileCount / (decimal)EpisodeCount * 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SeasonStatisticsResourceMapper
|
||||
{
|
||||
public static SeasonStatisticsResource ToResource(this SeasonStatistics model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new SeasonStatisticsResource
|
||||
{
|
||||
NextAiring = model.NextAiring,
|
||||
PreviousAiring = model.PreviousAiring,
|
||||
EpisodeFileCount = model.EpisodeFileCount,
|
||||
EpisodeCount = model.EpisodeFileCount,
|
||||
TotalEpisodeCount = model.TotalEpisodeCount,
|
||||
SizeOnDisk = model.SizeOnDisk
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Nancy;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Api.Series
|
||||
|
@ -19,11 +19,12 @@ namespace NzbDrone.Api.Series
|
|||
|
||||
private Response SaveAll()
|
||||
{
|
||||
//Read from request
|
||||
var series = Request.Body.FromJson<List<SeriesResource>>().InjectTo<List<Core.Tv.Series>>();
|
||||
var resources = Request.Body.FromJson<List<SeriesResource>>();
|
||||
|
||||
var series = resources.Select(seriesResource => seriesResource.ToModel(_seriesService.GetSeries(seriesResource.Id))).ToList();
|
||||
|
||||
return _seriesService.UpdateSeries(series)
|
||||
.InjectTo<List<SeriesResource>>()
|
||||
.ToResource()
|
||||
.AsResponse(HttpStatusCode.Accepted);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ using NzbDrone.Api.Extensions;
|
|||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.Mapping;
|
||||
|
||||
namespace NzbDrone.Api.Series
|
||||
{
|
||||
|
@ -31,7 +30,7 @@ namespace NzbDrone.Api.Series
|
|||
{
|
||||
foreach (var currentSeries in series)
|
||||
{
|
||||
var resource = currentSeries.InjectTo<SeriesResource>();
|
||||
var resource = currentSeries.ToResource();
|
||||
var poster = currentSeries.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||
if (poster != null)
|
||||
{
|
||||
|
|
|
@ -10,7 +10,6 @@ using NzbDrone.Core.MediaFiles.Events;
|
|||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.SeriesStats;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
using NzbDrone.Core.DataAugmentation.Scene;
|
||||
|
@ -84,14 +83,14 @@ namespace NzbDrone.Api.Series
|
|||
private SeriesResource GetSeries(int id)
|
||||
{
|
||||
var series = _seriesService.GetSeries(id);
|
||||
return GetSeriesResource(series);
|
||||
return MapToResource(series);
|
||||
}
|
||||
|
||||
private SeriesResource GetSeriesResource(Core.Tv.Series series)
|
||||
private SeriesResource MapToResource(Core.Tv.Series series)
|
||||
{
|
||||
if (series == null) return null;
|
||||
|
||||
var resource = series.InjectTo<SeriesResource>();
|
||||
var resource = series.ToResource();
|
||||
MapCoversToLocal(resource);
|
||||
FetchAndLinkSeriesStatistics(resource);
|
||||
PopulateAlternateTitles(resource);
|
||||
|
@ -102,7 +101,7 @@ namespace NzbDrone.Api.Series
|
|||
private List<SeriesResource> AllSeries()
|
||||
{
|
||||
var seriesStats = _seriesStatisticsService.SeriesStatistics();
|
||||
var seriesResources = ToListResource(_seriesService.GetAllSeries);
|
||||
var seriesResources = _seriesService.GetAllSeries().ToResource();
|
||||
|
||||
MapCoversToLocal(seriesResources.ToArray());
|
||||
LinkSeriesStatistics(seriesResources, seriesStats);
|
||||
|
@ -113,14 +112,16 @@ namespace NzbDrone.Api.Series
|
|||
|
||||
private int AddSeries(SeriesResource seriesResource)
|
||||
{
|
||||
var series = _seriesService.AddSeries(seriesResource.InjectTo<Core.Tv.Series>());
|
||||
var model = seriesResource.ToModel();
|
||||
|
||||
return series.Id;
|
||||
return _seriesService.AddSeries(model).Id;
|
||||
}
|
||||
|
||||
private void UpdateSeries(SeriesResource seriesResource)
|
||||
{
|
||||
GetNewId<Core.Tv.Series>(_seriesService.UpdateSeries, seriesResource);
|
||||
var model = seriesResource.ToModel(_seriesService.GetSeries(seriesResource.Id));
|
||||
|
||||
_seriesService.UpdateSeries(model);
|
||||
|
||||
BroadcastResourceChange(ModelAction.Updated, seriesResource);
|
||||
}
|
||||
|
@ -153,9 +154,11 @@ namespace NzbDrone.Api.Series
|
|||
|
||||
private void LinkSeriesStatistics(List<SeriesResource> resources, List<SeriesStatistics> seriesStatistics)
|
||||
{
|
||||
var dictSeriesStats = seriesStatistics.ToDictionary(v => v.SeriesId);
|
||||
|
||||
foreach (var series in resources)
|
||||
{
|
||||
var stats = seriesStatistics.SingleOrDefault(ss => ss.SeriesId == series.Id);
|
||||
var stats = dictSeriesStats.GetValueOrDefault(series.Id);
|
||||
if (stats == null) continue;
|
||||
|
||||
LinkSeriesStatistics(series, stats);
|
||||
|
@ -173,9 +176,11 @@ namespace NzbDrone.Api.Series
|
|||
|
||||
if (seriesStatistics.SeasonStatistics != null)
|
||||
{
|
||||
var dictSeasonStats = seriesStatistics.SeasonStatistics.ToDictionary(v => v.SeasonNumber);
|
||||
|
||||
foreach (var season in resource.Seasons)
|
||||
{
|
||||
season.Statistics = seriesStatistics.SeasonStatistics.SingleOrDefault(s => s.SeasonNumber == season.SeasonNumber).InjectTo<SeasonStatisticsResource>();
|
||||
season.Statistics = SeasonStatisticsResourceMapper.ToResource(dictSeasonStats.GetValueOrDefault(season.SeasonNumber));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -194,7 +199,7 @@ namespace NzbDrone.Api.Series
|
|||
|
||||
if (mappings == null) return;
|
||||
|
||||
resource.AlternateTitles = mappings.InjectTo<List<AlternateTitleResource>>();
|
||||
resource.AlternateTitles = mappings.Select(v => new AlternateTitleResource { Title = v.Title, SeasonNumber = v.SeasonNumber, SceneSeasonNumber = v.SceneSeasonNumber }).ToList();
|
||||
}
|
||||
|
||||
public void Handle(EpisodeImportedEvent message)
|
||||
|
@ -221,7 +226,7 @@ namespace NzbDrone.Api.Series
|
|||
|
||||
public void Handle(SeriesDeletedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Deleted, message.Series.InjectTo<SeriesResource>());
|
||||
BroadcastResourceChange(ModelAction.Deleted, message.Series.ToResource());
|
||||
}
|
||||
|
||||
public void Handle(SeriesRenamedEvent message)
|
||||
|
|
|
@ -33,7 +33,6 @@ namespace NzbDrone.Api.Series
|
|||
public int? EpisodeFileCount { get; set; }
|
||||
public long? SizeOnDisk { get; set; }
|
||||
public SeriesStatusType Status { get; set; }
|
||||
public string ProfileName { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public DateTime? NextAiring { get; set; }
|
||||
public DateTime? PreviousAiring { get; set; }
|
||||
|
@ -90,4 +89,139 @@ namespace NzbDrone.Api.Series
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SeriesResourceMapper
|
||||
{
|
||||
public static SeriesResource ToResource(this Core.Tv.Series model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new SeriesResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
Title = model.Title,
|
||||
//AlternateTitles
|
||||
SortTitle = model.SortTitle,
|
||||
|
||||
//TotalEpisodeCount
|
||||
//EpisodeCount
|
||||
//EpisodeFileCount
|
||||
//SizeOnDisk
|
||||
Status = model.Status,
|
||||
Overview = model.Overview,
|
||||
//NextAiring
|
||||
//PreviousAiring
|
||||
Network = model.Network,
|
||||
AirTime = model.AirTime,
|
||||
Images = model.Images,
|
||||
|
||||
Seasons = model.Seasons.ToResource(),
|
||||
Year = model.Year,
|
||||
|
||||
Path = model.Path,
|
||||
ProfileId = model.ProfileId,
|
||||
|
||||
SeasonFolder = model.SeasonFolder,
|
||||
Monitored = model.Monitored,
|
||||
|
||||
UseSceneNumbering = model.UseSceneNumbering,
|
||||
Runtime = model.Runtime,
|
||||
TvdbId = model.TvdbId,
|
||||
TvRageId = model.TvRageId,
|
||||
TvMazeId = model.TvMazeId,
|
||||
FirstAired = model.FirstAired,
|
||||
LastInfoSync = model.LastInfoSync,
|
||||
SeriesType = model.SeriesType,
|
||||
CleanTitle = model.CleanTitle,
|
||||
ImdbId = model.ImdbId,
|
||||
TitleSlug = model.TitleSlug,
|
||||
RootFolderPath = model.RootFolderPath,
|
||||
Certification = model.Certification,
|
||||
Genres = model.Genres,
|
||||
Tags = model.Tags,
|
||||
Added = model.Added,
|
||||
AddOptions = model.AddOptions,
|
||||
Ratings = model.Ratings
|
||||
};
|
||||
}
|
||||
|
||||
public static Core.Tv.Series ToModel(this SeriesResource resource)
|
||||
{
|
||||
if (resource == null) return null;
|
||||
|
||||
return new Core.Tv.Series
|
||||
{
|
||||
Id = resource.Id,
|
||||
|
||||
Title = resource.Title,
|
||||
//AlternateTitles
|
||||
SortTitle = resource.SortTitle,
|
||||
|
||||
//TotalEpisodeCount
|
||||
//EpisodeCount
|
||||
//EpisodeFileCount
|
||||
//SizeOnDisk
|
||||
Status = resource.Status,
|
||||
Overview = resource.Overview,
|
||||
//NextAiring
|
||||
//PreviousAiring
|
||||
Network = resource.Network,
|
||||
AirTime = resource.AirTime,
|
||||
Images = resource.Images,
|
||||
|
||||
Seasons = resource.Seasons.ToModel(),
|
||||
Year = resource.Year,
|
||||
|
||||
Path = resource.Path,
|
||||
ProfileId = resource.ProfileId,
|
||||
|
||||
SeasonFolder = resource.SeasonFolder,
|
||||
Monitored = resource.Monitored,
|
||||
|
||||
UseSceneNumbering = resource.UseSceneNumbering,
|
||||
Runtime = resource.Runtime,
|
||||
TvdbId = resource.TvdbId,
|
||||
TvRageId = resource.TvRageId,
|
||||
TvMazeId = resource.TvMazeId,
|
||||
FirstAired = resource.FirstAired,
|
||||
LastInfoSync = resource.LastInfoSync,
|
||||
SeriesType = resource.SeriesType,
|
||||
CleanTitle = resource.CleanTitle,
|
||||
ImdbId = resource.ImdbId,
|
||||
TitleSlug = resource.TitleSlug,
|
||||
RootFolderPath = resource.RootFolderPath,
|
||||
Certification = resource.Certification,
|
||||
Genres = resource.Genres,
|
||||
Tags = resource.Tags,
|
||||
Added = resource.Added,
|
||||
AddOptions = resource.AddOptions,
|
||||
Ratings = resource.Ratings
|
||||
};
|
||||
}
|
||||
|
||||
public static Core.Tv.Series ToModel(this SeriesResource resource, Core.Tv.Series series)
|
||||
{
|
||||
series.TvdbId = resource.TvdbId;
|
||||
|
||||
series.Seasons = resource.Seasons.ToModel();
|
||||
series.Path = resource.Path;
|
||||
series.ProfileId = resource.ProfileId;
|
||||
|
||||
series.SeasonFolder = resource.SeasonFolder;
|
||||
series.Monitored = resource.Monitored;
|
||||
|
||||
series.SeriesType = resource.SeriesType;
|
||||
series.RootFolderPath = resource.RootFolderPath;
|
||||
series.Tags = resource.Tags;
|
||||
series.AddOptions = resource.AddOptions;
|
||||
|
||||
return series;
|
||||
}
|
||||
|
||||
public static List<SeriesResource> ToResource(this IEnumerable<Core.Tv.Series> series)
|
||||
{
|
||||
return series.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Tags;
|
||||
|
@ -18,34 +17,38 @@ namespace NzbDrone.Api.Tags
|
|||
{
|
||||
_tagService = tagService;
|
||||
|
||||
GetResourceById = Get;
|
||||
GetResourceAll = GetAll;
|
||||
CreateResource = Create;
|
||||
UpdateResource = Update;
|
||||
DeleteResource = Delete;
|
||||
GetResourceById = GetTag;
|
||||
GetResourceAll = GetAllTags;
|
||||
CreateResource = CreateTag;
|
||||
UpdateResource = UpdateTag;
|
||||
DeleteResource = DeleteTag;
|
||||
}
|
||||
|
||||
private TagResource Get(int id)
|
||||
private TagResource GetTag(int id)
|
||||
{
|
||||
return _tagService.GetTag(id).InjectTo<TagResource>();
|
||||
return _tagService.GetTag(id).ToResource();
|
||||
}
|
||||
|
||||
private List<TagResource> GetAll()
|
||||
private List<TagResource> GetAllTags()
|
||||
{
|
||||
return ToListResource(_tagService.All);
|
||||
return _tagService.All().ToResource();
|
||||
}
|
||||
|
||||
private int Create(TagResource resource)
|
||||
private int CreateTag(TagResource resource)
|
||||
{
|
||||
return _tagService.Add(resource.InjectTo<Tag>()).Id;
|
||||
var model = resource.ToModel();
|
||||
|
||||
return _tagService.Add(model).Id;
|
||||
}
|
||||
|
||||
private void Update(TagResource resource)
|
||||
private void UpdateTag(TagResource resource)
|
||||
{
|
||||
_tagService.Update(resource.InjectTo<Tag>());
|
||||
var model = resource.ToModel();
|
||||
|
||||
_tagService.Update(model);
|
||||
}
|
||||
|
||||
private void Delete(int id)
|
||||
private void DeleteTag(int id)
|
||||
{
|
||||
_tagService.Delete(id);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Tags;
|
||||
|
||||
namespace NzbDrone.Api.Tags
|
||||
{
|
||||
|
@ -7,4 +10,36 @@ namespace NzbDrone.Api.Tags
|
|||
{
|
||||
public string Label { get; set; }
|
||||
}
|
||||
|
||||
public static class TagResourceMapper
|
||||
{
|
||||
public static TagResource ToResource(this Tag model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new TagResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
Label = model.Label
|
||||
};
|
||||
}
|
||||
|
||||
public static Tag ToModel(this TagResource resource)
|
||||
{
|
||||
if (resource == null) return null;
|
||||
|
||||
return new Tag
|
||||
{
|
||||
Id = resource.Id,
|
||||
|
||||
Label = resource.Label
|
||||
};
|
||||
}
|
||||
|
||||
public static List<TagResource> ToResource(this IEnumerable<Tag> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using System.Linq;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.Update;
|
||||
using NzbDrone.Api.Mapping;
|
||||
|
||||
namespace NzbDrone.Api.Update
|
||||
{
|
||||
|
@ -20,7 +19,7 @@ namespace NzbDrone.Api.Update
|
|||
{
|
||||
var resources = _recentUpdateProvider.GetRecentUpdatePackages()
|
||||
.OrderByDescending(u => u.Version)
|
||||
.InjectTo<List<UpdateResource>>();
|
||||
.ToResource();
|
||||
|
||||
if (resources.Any())
|
||||
{
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Update;
|
||||
|
@ -20,4 +22,32 @@ namespace NzbDrone.Api.Update
|
|||
public UpdateChanges Changes { get; set; }
|
||||
public string Hash { get; set; }
|
||||
}
|
||||
|
||||
public static class UpdateResourceMapper
|
||||
{
|
||||
public static UpdateResource ToResource(this UpdatePackage model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new UpdateResource
|
||||
{
|
||||
Version = model.Version,
|
||||
|
||||
Branch = model.Branch,
|
||||
ReleaseDate = model.ReleaseDate,
|
||||
FileName = model.FileName,
|
||||
Url = model.Url,
|
||||
//Installed
|
||||
//Installable
|
||||
//Latest
|
||||
Changes = model.Changes,
|
||||
Hash = model.Hash,
|
||||
};
|
||||
}
|
||||
|
||||
public static List<UpdateResource> ToResource(this IEnumerable<UpdatePackage> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace NzbDrone.Api.Wanted
|
|||
pagingSpec.FilterExpression = v => v.Monitored == true && v.Series.Monitored == true;
|
||||
}
|
||||
|
||||
PagingResource<EpisodeResource> resource = ApplyToPage(_episodeCutoffService.EpisodesWhereCutoffUnmet, pagingSpec);
|
||||
var resource = ApplyToPage(_episodeCutoffService.EpisodesWhereCutoffUnmet, pagingSpec, v => MapToResource(v, true, true));
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace NzbDrone.Api.Wanted
|
|||
pagingSpec.FilterExpression = v => v.Monitored == true && v.Series.Monitored == true;
|
||||
}
|
||||
|
||||
PagingResource<EpisodeResource> resource = ApplyToPage(v => _episodeService.EpisodesWithoutFiles(v), pagingSpec);
|
||||
var resource = ApplyToPage(_episodeService.EpisodesWithoutFiles, pagingSpec, v => MapToResource(v, true, false));
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
|
|
@ -7,5 +7,4 @@
|
|||
<package id="Nancy.Authentication.Forms" version="0.23.2" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net40" />
|
||||
<package id="NLog" version="4.3.4" targetFramework="net40" />
|
||||
<package id="ValueInjecter" version="2.3.3" targetFramework="net40" />
|
||||
</packages>
|
|
@ -27,7 +27,6 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
int compare = new QualityModelComparer(profile).Compare(newQuality, currentQuality);
|
||||
if (compare <= 0)
|
||||
{
|
||||
_logger.Debug("existing item has better or equal quality. skipping");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -42,29 +41,28 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
|
||||
public bool CutoffNotMet(Profile profile, QualityModel currentQuality, QualityModel newQuality = null)
|
||||
{
|
||||
int compare = new QualityModelComparer(profile).Compare(currentQuality.Quality, profile.Cutoff);
|
||||
var compare = new QualityModelComparer(profile).Compare(currentQuality.Quality, profile.Cutoff);
|
||||
|
||||
if (compare >= 0)
|
||||
if (compare < 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (newQuality != null && IsRevisionUpgrade(currentQuality, newQuality))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
_logger.Debug("Existing item meets cut-off. skipping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsRevisionUpgrade(QualityModel currentQuality, QualityModel newQuality)
|
||||
{
|
||||
int compare = newQuality.Revision.CompareTo(currentQuality.Revision);
|
||||
var compare = newQuality.Revision.CompareTo(currentQuality.Revision);
|
||||
|
||||
if (currentQuality.Quality == newQuality.Quality && compare > 0)
|
||||
{
|
||||
_logger.Debug("New quality is a better revision for existing quality");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.TraceException(string.Format("Ignored hashing error during scan for {0}", folder), ex);
|
||||
_logger.Trace(ex, "Ignored hashing error during scan for {0}", folder);
|
||||
}
|
||||
|
||||
foreach (var file in files.OrderBy(v => v))
|
||||
|
@ -187,7 +187,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.TraceException(string.Format("Ignored hashing error during scan for {0}", file), ex);
|
||||
_logger.Trace(ex, "Ignored hashing error during scan for {0}", file);
|
||||
}
|
||||
|
||||
return HashConverter.GetHash(data.ToString()).ToHexString();
|
||||
|
|
|
@ -27,13 +27,11 @@ namespace NzbDrone.Core.Download
|
|||
return base.Active().Where(c => c.Enable).ToList();
|
||||
}
|
||||
|
||||
public override DownloadClientDefinition GetProviderCharacteristics(IDownloadClient provider, DownloadClientDefinition definition)
|
||||
public override void SetProviderCharacteristics(IDownloadClient provider, DownloadClientDefinition definition)
|
||||
{
|
||||
definition = base.GetProviderCharacteristics(provider, definition);
|
||||
base.SetProviderCharacteristics(provider, definition);
|
||||
|
||||
definition.Protocol = provider.Protocol;
|
||||
|
||||
return definition;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,7 +37,8 @@ namespace NzbDrone.Core.Download
|
|||
|
||||
public IDownloadClient MapDownloadClient(IDownloadClient downloadClient)
|
||||
{
|
||||
downloadClient.Definition = _downloadClientFactory.GetProviderCharacteristics(downloadClient, (DownloadClientDefinition)downloadClient.Definition);
|
||||
_downloadClientFactory.SetProviderCharacteristics(downloadClient, (DownloadClientDefinition)downloadClient.Definition);
|
||||
|
||||
return downloadClient;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,10 @@ namespace NzbDrone.Core.HealthCheck
|
|||
public string Message { get; set; }
|
||||
public HttpUri WikiUrl { get; set; }
|
||||
|
||||
public HealthCheck()
|
||||
{
|
||||
}
|
||||
|
||||
public HealthCheck(Type source)
|
||||
{
|
||||
Source = source;
|
||||
|
|
|
@ -37,15 +37,13 @@ namespace NzbDrone.Core.Indexers
|
|||
return base.Active().Where(c => c.Enable).ToList();
|
||||
}
|
||||
|
||||
public override IndexerDefinition GetProviderCharacteristics(IIndexer provider, IndexerDefinition definition)
|
||||
public override void SetProviderCharacteristics(IIndexer provider, IndexerDefinition definition)
|
||||
{
|
||||
definition = base.GetProviderCharacteristics(provider, definition);
|
||||
base.SetProviderCharacteristics(provider, definition);
|
||||
|
||||
definition.Protocol = provider.Protocol;
|
||||
definition.SupportsRss = provider.SupportsRss;
|
||||
definition.SupportsSearch = provider.SupportsSearch;
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
public List<IIndexer> RssEnabled()
|
||||
|
|
|
@ -42,16 +42,14 @@ namespace NzbDrone.Core.Notifications
|
|||
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnRename).ToList();
|
||||
}
|
||||
|
||||
public override NotificationDefinition GetProviderCharacteristics(INotification provider, NotificationDefinition definition)
|
||||
public override void SetProviderCharacteristics(INotification provider, NotificationDefinition definition)
|
||||
{
|
||||
definition = base.GetProviderCharacteristics(provider, definition);
|
||||
base.SetProviderCharacteristics(provider, definition);
|
||||
|
||||
definition.SupportsOnGrab = provider.SupportsOnGrab;
|
||||
definition.SupportsOnDownload = provider.SupportsOnDownload;
|
||||
definition.SupportsOnUpgrade = provider.SupportsOnUpgrade;
|
||||
definition.SupportsOnRename = provider.SupportsOnRename;
|
||||
|
||||
return definition;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,9 +105,6 @@
|
|||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Omu.ValueInjecter">
|
||||
<HintPath>..\packages\ValueInjecter.2.3.3\lib\net35\Omu.ValueInjecter.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Prowlin">
|
||||
<HintPath>..\packages\Prowlin.0.9.4456.26422\lib\net40\Prowlin.dll</HintPath>
|
||||
</Reference>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using System.Linq;
|
||||
using FluentValidation.Validators;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Core.Profiles.Delay
|
||||
{
|
||||
|
@ -20,14 +19,14 @@ namespace NzbDrone.Core.Profiles.Delay
|
|||
{
|
||||
if (context.PropertyValue == null) return true;
|
||||
|
||||
var delayProfile = new DelayProfile();
|
||||
delayProfile.InjectFrom(context.ParentContext.InstanceToValidate);
|
||||
dynamic instance = context.ParentContext.InstanceToValidate;
|
||||
var instanceId = (int)instance.Id;
|
||||
|
||||
var collection = context.PropertyValue as HashSet<int>;
|
||||
|
||||
if (collection == null || collection.Empty()) return true;
|
||||
|
||||
return _delayProfileService.All().None(d => d.Id != delayProfile.Id && d.Tags.Intersect(collection).Any());
|
||||
return _delayProfileService.All().None(d => d.Id != instanceId && d.Tags.Intersect(collection).Any());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@ namespace NzbDrone.Core.ThingiProvider
|
|||
void Delete(int id);
|
||||
IEnumerable<TProviderDefinition> GetDefaultDefinitions();
|
||||
IEnumerable<TProviderDefinition> GetPresetDefinitions(TProviderDefinition providerDefinition);
|
||||
TProviderDefinition GetProviderCharacteristics(TProvider provider, TProviderDefinition definition);
|
||||
void SetProviderCharacteristics(TProviderDefinition definition);
|
||||
void SetProviderCharacteristics(TProvider provider, TProviderDefinition definition);
|
||||
TProvider GetInstance(TProviderDefinition definition);
|
||||
ValidationResult Test(TProviderDefinition definition);
|
||||
object ConnectData(TProviderDefinition definition, string stage, IDictionary<string, object> query );
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue