mirror of https://github.com/lidarr/Lidarr
Rewrote the RequestGenerator to support paging and other refactorings.
This commit is contained in:
parent
58b01b91d5
commit
fc75783fbe
|
@ -1,14 +1,14 @@
|
|||
using Moq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.TitansOfTv;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NzbDrone.Core.Indexers.TitansOfTv;
|
||||
|
||||
namespace NzbDrone.Core.Test.IndexerTests.TitansOfTvTests
|
||||
{
|
||||
|
@ -21,12 +21,12 @@ namespace NzbDrone.Core.Test.IndexerTests.TitansOfTvTests
|
|||
Subject.Definition = new IndexerDefinition
|
||||
{
|
||||
Name = "TitansOfTV",
|
||||
Settings = new TitansOfTvSettings { ApiKey = "abc", BaseUrl = "https://titansof.tv/api/torrents" }
|
||||
Settings = new TitansOfTvSettings { ApiKey = "abc", BaseUrl = "https://titansof.tv/api" }
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_parse_recent_feed_from_BroadcastheNet()
|
||||
public void should_parse_recent_feed_from_TitansOfTv()
|
||||
{
|
||||
var recentFeed = ReadAllText(@"Files/Indexers/TitansOfTv/RecentFeed.json");
|
||||
|
||||
|
@ -59,7 +59,8 @@ namespace NzbDrone.Core.Test.IndexerTests.TitansOfTvTests
|
|||
|
||||
private void VerifyBackOff()
|
||||
{
|
||||
// TODO How to detect (and implement) back-off logic.
|
||||
Mocker.GetMock<IIndexerStatusService>()
|
||||
.Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -8,38 +8,30 @@ namespace NzbDrone.Core.Indexers.TitansOfTv
|
|||
{
|
||||
public class TitansOfTv : HttpIndexerBase<TitansOfTvSettings>
|
||||
{
|
||||
public TitansOfTv(IHttpClient httpClient, IConfigService configService, IParsingService parsingService, Logger logger)
|
||||
: base(httpClient, configService, parsingService, logger)
|
||||
public TitansOfTv(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
|
||||
: base(httpClient, indexerStatusService, configService, parsingService, logger)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Titans of TV";
|
||||
}
|
||||
get { return "Titans of TV"; }
|
||||
}
|
||||
|
||||
public override DownloadProtocol Protocol
|
||||
{
|
||||
get
|
||||
{
|
||||
return DownloadProtocol.Torrent;
|
||||
}
|
||||
}
|
||||
public override DownloadProtocol Protocol { get { return DownloadProtocol.Torrent; } }
|
||||
public override bool SupportsRss { get { return true; } }
|
||||
public override bool SupportsSearch { get { return true; } }
|
||||
public override int PageSize { get { return 100; } }
|
||||
|
||||
public override IIndexerRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
return new TitansOfTvRequestGenerator() { Settings = Settings };
|
||||
return new TitansOfTvRequestGenerator() { Settings = Settings, PageSize = PageSize };
|
||||
}
|
||||
|
||||
public override IParseIndexerResponse GetParser()
|
||||
{
|
||||
return new TitansOfTvParser();
|
||||
}
|
||||
|
||||
public override Boolean SupportsSearch { get { return true; } }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,16 +3,26 @@ using System.Collections.Generic;
|
|||
|
||||
namespace NzbDrone.Core.Indexers.TitansOfTv
|
||||
{
|
||||
public class Result
|
||||
public class TitansOfTvApiResult
|
||||
{
|
||||
public string code { get; set; }
|
||||
public int http_code { get; set; }
|
||||
public int total { get; set; }
|
||||
public int offset { get; set; }
|
||||
public int limit { get; set; }
|
||||
public List<TitansOfTvTorrent> results { get; set; }
|
||||
}
|
||||
|
||||
public class TitansOfTvTorrent
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string series_id { get; set; }
|
||||
public string episode_id { get; set; }
|
||||
public string season_id { get; set; }
|
||||
public string seeders { get; set; }
|
||||
public string leechers { get; set; }
|
||||
public string size { get; set; }
|
||||
public string snatched { get; set; }
|
||||
public int? seeders { get; set; }
|
||||
public int? leechers { get; set; }
|
||||
public long size { get; set; }
|
||||
public int? snatched { get; set; }
|
||||
public int user_id { get; set; }
|
||||
public string anonymous { get; set; }
|
||||
public string container { get; set; }
|
||||
|
@ -29,17 +39,10 @@ namespace NzbDrone.Core.Indexers.TitansOfTv
|
|||
public string episode { get; set; }
|
||||
public string series { get; set; }
|
||||
public string network { get; set; }
|
||||
public string mediainfo { get; set; }
|
||||
public string download { get; set; }
|
||||
public string additional { get; set; }
|
||||
public string episodeUrl { get; set; }
|
||||
}
|
||||
|
||||
public class ApiResult
|
||||
{
|
||||
public string code { get; set; }
|
||||
public int http_code { get; set; }
|
||||
public int total { get; set; }
|
||||
public int offset { get; set; }
|
||||
public int limit { get; set; }
|
||||
public List<Result> results { get; set; }
|
||||
public string commentUrl { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Indexers.Exceptions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
|
@ -33,20 +33,24 @@ namespace NzbDrone.Core.Indexers.TitansOfTv
|
|||
}
|
||||
|
||||
var content = indexerResponse.HttpResponse.Content;
|
||||
var parsed = JsonConvert.DeserializeObject<ApiResult>(content);
|
||||
var parsed = Json.Deserialize<TitansOfTvApiResult>(content);
|
||||
var protocol = indexerResponse.HttpRequest.Url.Scheme + ":";
|
||||
|
||||
foreach (var parsedItem in parsed.results)
|
||||
{
|
||||
var release = new TorrentInfo();
|
||||
release.Guid = String.Format("ToTV-{0}", parsedItem.id);
|
||||
release.Guid = string.Format("ToTV-{0}", parsedItem.id);
|
||||
release.DownloadUrl = RegexProtocol.Replace(parsedItem.download, protocol);
|
||||
release.InfoUrl = RegexProtocol.Replace(parsedItem.episodeUrl, protocol);
|
||||
if (parsedItem.commentUrl.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
release.CommentUrl = RegexProtocol.Replace(parsedItem.commentUrl, protocol);
|
||||
}
|
||||
release.DownloadProtocol = DownloadProtocol.Torrent;
|
||||
release.Title = parsedItem.release_name;
|
||||
release.Size = Convert.ToInt64(parsedItem.size);
|
||||
release.Seeders = Convert.ToInt32(parsedItem.seeders);
|
||||
release.Peers = Convert.ToInt32(parsedItem.leechers) + release.Seeders;
|
||||
release.Size = parsedItem.size;
|
||||
release.Seeders = parsedItem.seeders;
|
||||
release.Peers = parsedItem.leechers + release.Seeders;
|
||||
release.PublishDate = parsedItem.created_at;
|
||||
results.Add(release);
|
||||
}
|
||||
|
|
|
@ -1,111 +1,119 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.TitansOfTv
|
||||
{
|
||||
public class TitansOfTvRequestGenerator : IIndexerRequestGenerator
|
||||
{
|
||||
public int MaxPages { get; set; }
|
||||
public int PageSize { get; set; }
|
||||
public TitansOfTvSettings Settings { get; set; }
|
||||
|
||||
public TitansOfTvRequestGenerator()
|
||||
{
|
||||
MaxPages = 30;
|
||||
PageSize = 100;
|
||||
}
|
||||
|
||||
public IList<IEnumerable<IndexerRequest>> GetRecentRequests()
|
||||
{
|
||||
var pageableRequests = new List<IEnumerable<IndexerRequest>>();
|
||||
var innerList = new List<IndexerRequest>();
|
||||
var httpRequest = BuildHttpRequest(GetBaseUrl());
|
||||
|
||||
innerList.Add(new IndexerRequest(httpRequest));
|
||||
pageableRequests.Add(innerList);
|
||||
pageableRequests.AddIfNotNull(GetPagedRequests(MaxPages));
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
private HttpRequest BuildHttpRequest(string url)
|
||||
public IList<IEnumerable<IndexerRequest>> GetSearchRequests(SingleEpisodeSearchCriteria searchCriteria)
|
||||
{
|
||||
var httpRequest = new HttpRequest(url, HttpAccept.Json);
|
||||
httpRequest.Headers["X-Authorization"] = Settings.ApiKey;
|
||||
var pageableRequests = new List<IEnumerable<IndexerRequest>>();
|
||||
|
||||
return httpRequest;
|
||||
pageableRequests.AddIfNotNull(GetPagedRequests(MaxPages,
|
||||
series_id: searchCriteria.Series.TvdbId,
|
||||
episode: string.Format("S{0:00}E{1:00}", searchCriteria.SeasonNumber, searchCriteria.EpisodeNumber)));
|
||||
|
||||
pageableRequests.AddIfNotNull(GetPagedRequests(MaxPages,
|
||||
series_id: searchCriteria.Series.TvdbId,
|
||||
season: string.Format("Season {0:00}", searchCriteria.SeasonNumber)));
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
public IList<IEnumerable<IndexerRequest>> GetSearchRequests(IndexerSearch.Definitions.SingleEpisodeSearchCriteria searchCriteria)
|
||||
public IList<IEnumerable<IndexerRequest>> GetSearchRequests(SeasonSearchCriteria searchCriteria)
|
||||
{
|
||||
var url = GetBaseUrl() + "&series_id={series}&episode={episode}";
|
||||
var requests = new List<IEnumerable<IndexerRequest>>();
|
||||
var innerList = new List<IndexerRequest>();
|
||||
requests.Add(innerList);
|
||||
var pageableRequests = new List<IEnumerable<IndexerRequest>>();
|
||||
|
||||
var httpRequest = BuildHttpRequest(url);
|
||||
var episodeString = String.Format("S{0:00}E{1:00}", searchCriteria.SeasonNumber, searchCriteria.EpisodeNumber);
|
||||
httpRequest.AddSegment("series", searchCriteria.Series.TvdbId.ToString(CultureInfo.InvariantCulture));
|
||||
httpRequest.AddSegment("episode", episodeString);
|
||||
// TODO: Search for all episodes?!?
|
||||
|
||||
var request = new IndexerRequest(httpRequest);
|
||||
innerList.Add(request);
|
||||
pageableRequests.AddIfNotNull(GetPagedRequests(MaxPages,
|
||||
series_id: searchCriteria.Series.TvdbId,
|
||||
season: string.Format("Season {0:00}", searchCriteria.SeasonNumber)));
|
||||
|
||||
return requests;
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
public IList<IEnumerable<IndexerRequest>> GetSearchRequests(IndexerSearch.Definitions.SeasonSearchCriteria searchCriteria)
|
||||
public IList<IEnumerable<IndexerRequest>> GetSearchRequests(DailyEpisodeSearchCriteria searchCriteria)
|
||||
{
|
||||
var url = GetBaseUrl() + "&series_id={series}&season={season}";
|
||||
var requests = new List<IEnumerable<IndexerRequest>>();
|
||||
var innerList = new List<IndexerRequest>();
|
||||
requests.Add(innerList);
|
||||
var pageableRequests = new List<IEnumerable<IndexerRequest>>();
|
||||
|
||||
var httpRequest = BuildHttpRequest(url);
|
||||
var seasonString = String.Format("Season {0:00}", searchCriteria.SeasonNumber);
|
||||
httpRequest.AddSegment("series", searchCriteria.Series.TvdbId.ToString(CultureInfo.InvariantCulture));
|
||||
httpRequest.AddSegment("season", seasonString);
|
||||
pageableRequests.AddIfNotNull(GetPagedRequests(MaxPages,
|
||||
series_id: searchCriteria.Series.TvdbId,
|
||||
air_date: searchCriteria.AirDate));
|
||||
|
||||
var request = new IndexerRequest(httpRequest);
|
||||
innerList.Add(request);
|
||||
|
||||
httpRequest = BuildHttpRequest(url);
|
||||
seasonString = String.Format("Season {0}", searchCriteria.SeasonNumber);
|
||||
httpRequest.AddSegment("series", searchCriteria.Series.TvdbId.ToString(CultureInfo.InvariantCulture));
|
||||
httpRequest.AddSegment("season", seasonString);
|
||||
|
||||
request = new IndexerRequest(httpRequest);
|
||||
innerList.Add(request);
|
||||
|
||||
return requests;
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
public IList<IEnumerable<IndexerRequest>> GetSearchRequests(IndexerSearch.Definitions.DailyEpisodeSearchCriteria searchCriteria)
|
||||
{
|
||||
var url = GetBaseUrl() + "&series_id={series}&air_date={air_date}";
|
||||
var requests = new List<IEnumerable<IndexerRequest>>();
|
||||
var innerList = new List<IndexerRequest>();
|
||||
|
||||
requests.Add(innerList);
|
||||
|
||||
var httpRequest = BuildHttpRequest(url);
|
||||
var airDate = searchCriteria.AirDate.ToString("yyyy-MM-dd");
|
||||
|
||||
httpRequest.AddSegment("series", searchCriteria.Series.TvdbId.ToString(CultureInfo.InvariantCulture));
|
||||
httpRequest.AddSegment("air_date", airDate);
|
||||
|
||||
var request = new IndexerRequest(httpRequest);
|
||||
innerList.Add(request);
|
||||
|
||||
return requests;
|
||||
}
|
||||
|
||||
public IList<IEnumerable<IndexerRequest>> GetSearchRequests(IndexerSearch.Definitions.AnimeEpisodeSearchCriteria searchCriteria)
|
||||
public IList<IEnumerable<IndexerRequest>> GetSearchRequests(AnimeEpisodeSearchCriteria searchCriteria)
|
||||
{
|
||||
return new List<IEnumerable<IndexerRequest>>();
|
||||
}
|
||||
|
||||
public IList<IEnumerable<IndexerRequest>> GetSearchRequests(IndexerSearch.Definitions.SpecialEpisodeSearchCriteria searchCriteria)
|
||||
public IList<IEnumerable<IndexerRequest>> GetSearchRequests(SpecialEpisodeSearchCriteria searchCriteria)
|
||||
{
|
||||
return new List<IEnumerable<IndexerRequest>>();
|
||||
}
|
||||
|
||||
private string GetBaseUrl()
|
||||
private IEnumerable<IndexerRequest> GetPagedRequests(int maxPages, int? series_id = null, string episode = null, string season = null, DateTime? air_date = null)
|
||||
{
|
||||
return Settings.BaseUrl + "?limit=100";
|
||||
var pageSize = PageSize;
|
||||
|
||||
if (pageSize == 0)
|
||||
{
|
||||
maxPages = 1;
|
||||
pageSize = 100;
|
||||
}
|
||||
|
||||
for (var page = 0; page < maxPages; page++)
|
||||
{
|
||||
var request = new IndexerRequest(string.Format("{0}/torrents?offset={1}&limit={2}", Settings.BaseUrl.TrimEnd('/'), page * pageSize, pageSize), HttpAccept.Json);
|
||||
request.HttpRequest.Headers.Add("X-Authorization", Settings.ApiKey);
|
||||
|
||||
if (series_id.HasValue)
|
||||
{
|
||||
request.HttpRequest.AddQueryParam("series_id", series_id.Value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
if (season != null)
|
||||
{
|
||||
request.HttpRequest.AddQueryParam("season", season);
|
||||
}
|
||||
|
||||
if (episode != null)
|
||||
{
|
||||
request.HttpRequest.AddQueryParam("episode", episode);
|
||||
}
|
||||
|
||||
if (air_date.HasValue)
|
||||
{
|
||||
request.HttpRequest.AddQueryParam("air_date", air_date.Value.ToString("yyyy-MM-dd"));
|
||||
}
|
||||
|
||||
yield return request;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,7 @@ using NzbDrone.Core.Validation;
|
|||
|
||||
namespace NzbDrone.Core.Indexers.TitansOfTv
|
||||
{
|
||||
|
||||
public class TitansOfTvSettingsValidator : AbstractValidator<TitansOfTvSettings>
|
||||
public class TitansOfTvSettingsValidator : AbstractValidator<TitansOfTvSettings>
|
||||
{
|
||||
public TitansOfTvSettingsValidator()
|
||||
{
|
||||
|
@ -20,7 +19,7 @@ namespace NzbDrone.Core.Indexers.TitansOfTv
|
|||
|
||||
public TitansOfTvSettings()
|
||||
{
|
||||
BaseUrl = "http://titansof.tv/api/torrents";
|
||||
BaseUrl = "http://titansof.tv/api";
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "API URL", Advanced = true, HelpText = "Do not change this unless you know what you're doing. Since your API key will be sent to that host.")]
|
||||
|
|
Loading…
Reference in New Issue