mirror of
https://github.com/Radarr/Radarr.git
synced 2024-11-04 10:02:40 +01:00
basic RSS fetch seems to be working.
download might still not work.
This commit is contained in:
parent
182192e0ba
commit
a1783a53a9
@ -5,6 +5,7 @@
|
|||||||
using NzbDrone.Api.Mapping;
|
using NzbDrone.Api.Mapping;
|
||||||
using NzbDrone.Api.RootFolders;
|
using NzbDrone.Api.RootFolders;
|
||||||
using NzbDrone.Api.Series;
|
using NzbDrone.Api.Series;
|
||||||
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Organizer;
|
using NzbDrone.Core.Organizer;
|
||||||
using NzbDrone.Core.RootFolders;
|
using NzbDrone.Core.RootFolders;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
@ -18,6 +19,7 @@ public class ResourceMappingFixture : TestBase
|
|||||||
[TestCase(typeof(Core.Tv.Episode), typeof(EpisodeResource))]
|
[TestCase(typeof(Core.Tv.Episode), typeof(EpisodeResource))]
|
||||||
[TestCase(typeof(RootFolder), typeof(RootFolderResource))]
|
[TestCase(typeof(RootFolder), typeof(RootFolderResource))]
|
||||||
[TestCase(typeof(NamingConfig), typeof(NamingConfigResource))]
|
[TestCase(typeof(NamingConfig), typeof(NamingConfigResource))]
|
||||||
|
[TestCase(typeof(IndexerDefinition), typeof(IndexerRepository))]
|
||||||
public void matching_fields(Type modelType, Type resourceType)
|
public void matching_fields(Type modelType, Type resourceType)
|
||||||
{
|
{
|
||||||
MappingValidation.ValidateMapping(modelType, resourceType);
|
MappingValidation.ValidateMapping(modelType, resourceType);
|
||||||
|
21
NzbDrone.Api/Indexers/IndexerModule.cs
Normal file
21
NzbDrone.Api/Indexers/IndexerModule.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Core.Indexers;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Indexers
|
||||||
|
{
|
||||||
|
public class IndexerModule : NzbDroneRestModule<IndexerResource>
|
||||||
|
{
|
||||||
|
private readonly IIndexerService _indexerService;
|
||||||
|
|
||||||
|
public IndexerModule(IIndexerService indexerService)
|
||||||
|
{
|
||||||
|
_indexerService = indexerService;
|
||||||
|
GetResourceAll = GetAll;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<IndexerResource> GetAll()
|
||||||
|
{
|
||||||
|
return ApplyToList(_indexerService.All);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
NzbDrone.Api/Indexers/IndexerResource.cs
Normal file
12
NzbDrone.Api/Indexers/IndexerResource.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using NzbDrone.Api.REST;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Indexers
|
||||||
|
{
|
||||||
|
public class IndexerResource : RestResource
|
||||||
|
{
|
||||||
|
public Boolean Enable { get; set; }
|
||||||
|
public String Name { get; set; }
|
||||||
|
public String Settings { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -94,6 +94,8 @@
|
|||||||
<Compile Include="Frontend\IndexModule.cs" />
|
<Compile Include="Frontend\IndexModule.cs" />
|
||||||
<Compile Include="Frontend\StaticResourceProvider.cs" />
|
<Compile Include="Frontend\StaticResourceProvider.cs" />
|
||||||
<Compile Include="Frontend\StaticResourceMapper.cs" />
|
<Compile Include="Frontend\StaticResourceMapper.cs" />
|
||||||
|
<Compile Include="Indexers\IndexerModule.cs" />
|
||||||
|
<Compile Include="Indexers\IndexerResource.cs" />
|
||||||
<Compile Include="Mapping\MappingValidation.cs" />
|
<Compile Include="Mapping\MappingValidation.cs" />
|
||||||
<Compile Include="Mapping\ResourceMappingException.cs" />
|
<Compile Include="Mapping\ResourceMappingException.cs" />
|
||||||
<Compile Include="Mapping\ValueInjectorExtensions.cs" />
|
<Compile Include="Mapping\ValueInjectorExtensions.cs" />
|
||||||
@ -103,6 +105,7 @@
|
|||||||
<Compile Include="Resolvers\EndTimeResolver.cs" />
|
<Compile Include="Resolvers\EndTimeResolver.cs" />
|
||||||
<Compile Include="Resolvers\NextAiringResolver.cs" />
|
<Compile Include="Resolvers\NextAiringResolver.cs" />
|
||||||
<Compile Include="Resolvers\NullableDatetimeToString.cs" />
|
<Compile Include="Resolvers\NullableDatetimeToString.cs" />
|
||||||
|
<Compile Include="REST\BadRequestException.cs" />
|
||||||
<Compile Include="REST\ResourceValidator.cs" />
|
<Compile Include="REST\ResourceValidator.cs" />
|
||||||
<Compile Include="REST\RestModule.cs" />
|
<Compile Include="REST\RestModule.cs" />
|
||||||
<Compile Include="REST\RestResource.cs" />
|
<Compile Include="REST\RestResource.cs" />
|
||||||
|
14
NzbDrone.Api/REST/BadRequestException.cs
Normal file
14
NzbDrone.Api/REST/BadRequestException.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using Nancy;
|
||||||
|
using NzbDrone.Api.ErrorManagement;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.REST
|
||||||
|
{
|
||||||
|
public class BadRequestException : ApiException
|
||||||
|
{
|
||||||
|
public BadRequestException(object content = null)
|
||||||
|
: base(HttpStatusCode.BadRequest, content)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,15 @@ public abstract class RestModule<TResource> : NancyModule
|
|||||||
protected ResourceValidator<TResource> SharedValidator { get; private set; }
|
protected ResourceValidator<TResource> SharedValidator { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
protected void ValidateId(int id)
|
||||||
|
{
|
||||||
|
if (id <= 0)
|
||||||
|
{
|
||||||
|
throw new BadRequestException(id + " is not a valid ID");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected RestModule(string modulePath)
|
protected RestModule(string modulePath)
|
||||||
: base(modulePath)
|
: base(modulePath)
|
||||||
{
|
{
|
||||||
@ -42,6 +51,7 @@ protected Action<int> DeleteResource
|
|||||||
_deleteResource = value;
|
_deleteResource = value;
|
||||||
Delete[ID_ROUTE] = options =>
|
Delete[ID_ROUTE] = options =>
|
||||||
{
|
{
|
||||||
|
ValidateId(options.Id);
|
||||||
DeleteResource((int)options.Id);
|
DeleteResource((int)options.Id);
|
||||||
return new Response { StatusCode = HttpStatusCode.OK };
|
return new Response { StatusCode = HttpStatusCode.OK };
|
||||||
};
|
};
|
||||||
@ -56,12 +66,7 @@ protected Func<int, TResource> GetResourceById
|
|||||||
_getResourceById = value;
|
_getResourceById = value;
|
||||||
Get[ID_ROUTE] = options =>
|
Get[ID_ROUTE] = options =>
|
||||||
{
|
{
|
||||||
int id;
|
ValidateId(options.Id);
|
||||||
if (!Int32.TryParse(options.Id, out id))
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
var resource = GetResourceById((int)options.Id);
|
var resource = GetResourceById((int)options.Id);
|
||||||
return resource.AsResponse();
|
return resource.AsResponse();
|
||||||
};
|
};
|
||||||
|
@ -43,7 +43,7 @@ public void Setup()
|
|||||||
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>())).Returns(false);
|
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>())).Returns(false);
|
||||||
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>())).Returns(false);
|
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>())).Returns(false);
|
||||||
|
|
||||||
_reports = new List<ReportInfo> {new ReportInfo()};
|
_reports = new List<ReportInfo> { new ReportInfo() };
|
||||||
_remoteEpisode = new RemoteEpisode();
|
_remoteEpisode = new RemoteEpisode();
|
||||||
|
|
||||||
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ReportInfo>()))
|
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ReportInfo>()))
|
||||||
@ -101,6 +101,25 @@ public void should_have_same_number_of_rejections_as_specs_that_failed()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_attempt_to_make_decision_if_remote_episode_is_null()
|
||||||
|
{
|
||||||
|
GivenSpecifications(_pass1, _pass2, _pass3);
|
||||||
|
|
||||||
|
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ReportInfo>()))
|
||||||
|
.Returns<RemoteEpisode>(null);
|
||||||
|
|
||||||
|
var results = Subject.GetRssDecision(_reports).ToList();
|
||||||
|
|
||||||
|
_pass1.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||||
|
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||||
|
_pass3.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||||
|
|
||||||
|
results.Should().BeEmpty();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
1
NzbDrone.Core.Test/Files/Indexers/Nzbx/nzbx_recent.json
Normal file
1
NzbDrone.Core.Test/Files/Indexers/Nzbx/nzbx_recent.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,22 @@
|
|||||||
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Indexers.Nzbx;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.IndexerTests.IntegerationTests
|
||||||
|
{
|
||||||
|
public class NzbxIntegerationTests : CoreTest<FetchFeedService>
|
||||||
|
{
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_able_to_fetch_rss()
|
||||||
|
{
|
||||||
|
UseRealHttp();
|
||||||
|
|
||||||
|
var indexer = new Nzbx();
|
||||||
|
|
||||||
|
Subject.FetchRss(indexer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
using NzbDrone.Core.Indexers.Nzbx;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.IndexerTests.ParserTests
|
||||||
|
{
|
||||||
|
public class NzbxParserFixture : CoreTest<NzbxParser>
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void should_be_able_to_parse_json()
|
||||||
|
{
|
||||||
|
var stream = OpenRead("Files", "Indexers", "Nzbx", "nzbx_recent.json");
|
||||||
|
|
||||||
|
var result = Subject.Process(stream).ToList();
|
||||||
|
|
||||||
|
result.Should().NotBeEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -132,6 +132,8 @@
|
|||||||
<Compile Include="Framework\NBuilderExtensions.cs" />
|
<Compile Include="Framework\NBuilderExtensions.cs" />
|
||||||
<Compile Include="IndexerSearchTests\SearchDefinitionFixture.cs" />
|
<Compile Include="IndexerSearchTests\SearchDefinitionFixture.cs" />
|
||||||
<Compile Include="IndexerTests\BasicRssParserFixture.cs" />
|
<Compile Include="IndexerTests\BasicRssParserFixture.cs" />
|
||||||
|
<Compile Include="IndexerTests\IntegerationTests\NzbxIntegerationTests.cs" />
|
||||||
|
<Compile Include="IndexerTests\ParserTests\NzbxParserFixture.cs" />
|
||||||
<Compile Include="JobTests\JobRepositoryFixture.cs" />
|
<Compile Include="JobTests\JobRepositoryFixture.cs" />
|
||||||
<Compile Include="JobTests\RenameSeasonJobFixture.cs" />
|
<Compile Include="JobTests\RenameSeasonJobFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\LanguageSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\LanguageSpecificationFixture.cs" />
|
||||||
@ -261,10 +263,10 @@
|
|||||||
<None Include="..\NzbDrone.Test.Common\App.config">
|
<None Include="..\NzbDrone.Test.Common\App.config">
|
||||||
<Link>App.config</Link>
|
<Link>App.config</Link>
|
||||||
</None>
|
</None>
|
||||||
<None Include="Files\RSS\nzbx_search.json">
|
<None Include="Files\Indexers\Nzbx\nzbx_search.json">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Include="Files\RSS\nzbx_recent.json">
|
<None Include="Files\Indexers\Nzbx\nzbx_recent.json">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<Content Include="Files\RSS\omgwtfnzbs.xml">
|
<Content Include="Files\RSS\omgwtfnzbs.xml">
|
||||||
|
@ -29,9 +29,12 @@ public IEnumerable<DownloadDecision> GetRssDecision(IEnumerable<ReportInfo> repo
|
|||||||
foreach (var report in reports)
|
foreach (var report in reports)
|
||||||
{
|
{
|
||||||
var parseResult = _parsingService.Map(report);
|
var parseResult = _parsingService.Map(report);
|
||||||
yield return new DownloadDecision(parseResult, GetGeneralRejectionReasons(parseResult).ToArray());
|
if (parseResult != null)
|
||||||
}
|
{
|
||||||
|
|
||||||
|
yield return new DownloadDecision(parseResult, GetGeneralRejectionReasons(parseResult).ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<DownloadDecision> GetSearchDecision(IEnumerable<ReportInfo> reports, SearchDefinitionBase searchDefinitionBase)
|
public IEnumerable<DownloadDecision> GetSearchDecision(IEnumerable<ReportInfo> reports, SearchDefinitionBase searchDefinitionBase)
|
||||||
|
@ -14,7 +14,7 @@ public virtual bool EnabledByDefault
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,15 @@ public override bool IsConfigured
|
|||||||
get { return Settings.IsValid; }
|
get { return Settings.IsValid; }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TSetting Settings { get; private set; }
|
public override bool EnabledByDefault
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TSetting Settings { get; private set; }
|
||||||
|
|
||||||
public void Handle(IndexerSettingUpdatedEvent message)
|
public void Handle(IndexerSettingUpdatedEvent message)
|
||||||
{
|
{
|
||||||
|
@ -5,6 +5,14 @@ namespace NzbDrone.Core.Indexers.Nzbx
|
|||||||
{
|
{
|
||||||
public class Nzbx : Indexer
|
public class Nzbx : Indexer
|
||||||
{
|
{
|
||||||
|
public override IParseFeed Parser
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new NzbxParser();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override string Name
|
public override string Name
|
||||||
{
|
{
|
||||||
get { return "nzbx"; }
|
get { return "nzbx"; }
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using NLog;
|
using NLog;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NzbDrone.Core.Model;
|
|
||||||
using NzbDrone.Core.Parser;
|
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Indexers.Nzbx
|
namespace NzbDrone.Core.Indexers.Nzbx
|
||||||
@ -14,9 +12,9 @@ public class NzbxParser : IParseFeed
|
|||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
private readonly JsonSerializer _serializer;
|
private readonly JsonSerializer _serializer;
|
||||||
|
|
||||||
public NzbxParser(Logger logger)
|
public NzbxParser()
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = LogManager.GetCurrentClassLogger();
|
||||||
_serializer = new JsonSerializer();
|
_serializer = new JsonSerializer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ public interface IParsingService
|
|||||||
{
|
{
|
||||||
LocalEpisode GetEpisodes(string fileName, Series series);
|
LocalEpisode GetEpisodes(string fileName, Series series);
|
||||||
Series GetSeries(string title);
|
Series GetSeries(string title);
|
||||||
RemoteEpisode Map(ReportInfo indexerParseResult);
|
RemoteEpisode Map(ReportInfo reportInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ParsingService : IParsingService
|
public class ParsingService : IParsingService
|
||||||
@ -65,9 +65,34 @@ public Series GetSeries(string title)
|
|||||||
return _seriesService.FindByTitle(searchTitle);
|
return _seriesService.FindByTitle(searchTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RemoteEpisode Map(ReportInfo indexerParseResult)
|
public RemoteEpisode Map(ReportInfo reportInfo)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var parsedInfo = Parser.ParseTitle(reportInfo.Title);
|
||||||
|
|
||||||
|
if (parsedInfo == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var series = _seriesService.FindByTitle(parsedInfo.SeriesTitle);
|
||||||
|
|
||||||
|
if (series == null)
|
||||||
|
{
|
||||||
|
_logger.Trace("No matching series {0}", parsedInfo.SeriesTitle);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var remoteEpisode = new RemoteEpisode
|
||||||
|
{
|
||||||
|
Series = series,
|
||||||
|
Episodes = GetEpisodes(parsedInfo, series),
|
||||||
|
FullSeason = parsedInfo.FullSeason,
|
||||||
|
Language = parsedInfo.Language,
|
||||||
|
Quality = parsedInfo.Quality,
|
||||||
|
Report = reportInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
return remoteEpisode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Episode> GetEpisodes(ParsedEpisodeInfo parsedEpisodeInfo, Series series)
|
private List<Episode> GetEpisodes(ParsedEpisodeInfo parsedEpisodeInfo, Series series)
|
||||||
|
@ -41,8 +41,9 @@ public void should_be_able_to_add_and_delete_series()
|
|||||||
var rootFolder = RootFolders.Post(new RootFolderResource { Path = Directory.GetCurrentDirectory() });
|
var rootFolder = RootFolders.Post(new RootFolderResource { Path = Directory.GetCurrentDirectory() });
|
||||||
|
|
||||||
series.RootFolderId = rootFolder.Id;
|
series.RootFolderId = rootFolder.Id;
|
||||||
|
series.QualityProfileId = 1;
|
||||||
|
|
||||||
Series.Post(series);
|
series = Series.Post(series);
|
||||||
|
|
||||||
Series.All().Should().HaveCount(1);
|
Series.All().Should().HaveCount(1);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user