From 7921dd3f96d3131fde57309520c9f892717abbb1 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Thu, 17 Dec 2015 00:46:02 -0800 Subject: [PATCH] Fixed: Removed Titans of TV tracker Closes #992 --- .../Files/Indexers/TitansOfTv/RecentFeed.json | 67 -------- .../TitansOfTvTests/TitansOfTvFixture.cs | 157 ------------------ .../NzbDrone.Core.Test.csproj | 4 - .../Migration/098_remove_titans_of_tv.cs | 14 ++ .../Indexers/TitansOfTv/TitansOfTv.cs | 37 ----- .../TitansOfTv/TitansOfTvApiResult.cs | 48 ------ .../Indexers/TitansOfTv/TitansOfTvParser.cs | 61 ------- .../TitansOfTv/TitansOfTvRequestGenerator.cs | 121 -------------- .../Indexers/TitansOfTv/TitansOfTvSettings.cs | 36 ---- src/NzbDrone.Core/NzbDrone.Core.csproj | 8 +- 10 files changed, 17 insertions(+), 536 deletions(-) delete mode 100644 src/NzbDrone.Core.Test/Files/Indexers/TitansOfTv/RecentFeed.json delete mode 100644 src/NzbDrone.Core.Test/IndexerTests/TitansOfTvTests/TitansOfTvFixture.cs create mode 100644 src/NzbDrone.Core/Datastore/Migration/098_remove_titans_of_tv.cs delete mode 100644 src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTv.cs delete mode 100644 src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvApiResult.cs delete mode 100644 src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvParser.cs delete mode 100644 src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvRequestGenerator.cs delete mode 100644 src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvSettings.cs diff --git a/src/NzbDrone.Core.Test/Files/Indexers/TitansOfTv/RecentFeed.json b/src/NzbDrone.Core.Test/Files/Indexers/TitansOfTv/RecentFeed.json deleted file mode 100644 index f593c3153..000000000 --- a/src/NzbDrone.Core.Test/Files/Indexers/TitansOfTv/RecentFeed.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "code": "SUCCESSFUL", - "http_code": 200, - "limit": "2", - "offset": 0, - "results": [ - { - "air_date": "20150623", - "anonymous": 1, - "codec": "x264", - "container": "MKV", - "created_at": "2015-06-25 04:13:44", - "download": "https://titansof.tv/api/torrents/19445/download?apikey=abc", - "ecommentUrl": "https://titansof.tv/series/287053/episode/5453241#comments", - "episode": "S02E04", - "episodeUrl": "https://titansof.tv/series/287053/episode/5453241", - "episode_id": "5453241", - "id": "19445", - "language": "en", - "leechers": 5, - "network": "truTV", - "origin": "Scene", - "release_name": "Series.Title.S02E04.720p.HDTV.x264-W4F", - "resolution": "720p", - "season": "", - "season_id": 0, - "seeders": 2, - "series": "Series Title", - "series_id": "287053", - "size": 435402993, - "snatched": 0, - "source": "HDTV", - "updated_at": "2015-06-25 04:13:44", - "user_id": 0 - }, - { - "air_date": "20150624", - "anonymous": 1, - "codec": "x264", - "container": "MKV", - "created_at": "2015-06-25 04:11:59", - "download": "https://titansof.tv/api/torrents/19444/download?apikey=abc", - "ecommentUrl": "https://titansof.tv/series/75382/episode/5443517#comments", - "episode": "S21E10", - "episodeUrl": "https://titansof.tv/series/75382/episode/5443517", - "episode_id": "5443517", - "id": "19444", - "language": "en", - "leechers": 0, - "network": "FX", - "origin": "User", - "release_name": "Series.Title.S21E10.720p.HDTV.x264-KOENiG", - "resolution": "720p", - "season": "", - "season_id": 0, - "seeders": 1, - "series": "Series Title", - "series_id": "75382", - "size": 949968933, - "snatched": 0, - "source": "HDTV", - "updated_at": "2015-06-25 04:11:59", - "user_id": 0 - } - ], - "total": 18546 -} \ No newline at end of file diff --git a/src/NzbDrone.Core.Test/IndexerTests/TitansOfTvTests/TitansOfTvFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/TitansOfTvTests/TitansOfTvFixture.cs deleted file mode 100644 index 4847b1efe..000000000 --- a/src/NzbDrone.Core.Test/IndexerTests/TitansOfTvTests/TitansOfTvFixture.cs +++ /dev/null @@ -1,157 +0,0 @@ -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; - -namespace NzbDrone.Core.Test.IndexerTests.TitansOfTvTests -{ - [TestFixture] - public class TitansOfTvFixture : CoreTest - { - [SetUp] - public void Setup() - { - Subject.Definition = new IndexerDefinition - { - Name = "TitansOfTV", - Settings = new TitansOfTvSettings { ApiKey = "abc", BaseUrl = "https://titansof.tv/api" } - }; - } - - [Test] - public void should_parse_recent_feed_from_TitansOfTv() - { - var recentFeed = ReadAllText(@"Files/Indexers/TitansOfTv/RecentFeed.json"); - - Mocker.GetMock() - .Setup(o => o.Execute(It.Is(v => v.Method == HttpMethod.GET))) - .Returns(r => new HttpResponse(r, new HttpHeader(), recentFeed)); - - var releases = Subject.FetchRecent(); - - releases.Should().HaveCount(2); - releases.First().Should().BeOfType(); - - var torrentInfo = releases.First() as TorrentInfo; - - torrentInfo.Guid.Should().Be("ToTV-19445"); - torrentInfo.Title.Should().Be("Series.Title.S02E04.720p.HDTV.x264-W4F"); - torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent); - torrentInfo.DownloadUrl.Should().Be("https://titansof.tv/api/torrents/19445/download?apikey=abc"); - torrentInfo.InfoUrl.Should().Be("https://titansof.tv/series/287053/episode/5453241"); - torrentInfo.CommentUrl.Should().BeNullOrEmpty(); - torrentInfo.Indexer.Should().Be(Subject.Definition.Name); - torrentInfo.PublishDate.Should().Be(DateTime.Parse("2015-06-25 04:13:44")); - torrentInfo.Size.Should().Be(435402993); - torrentInfo.InfoHash.Should().BeNullOrEmpty(); - torrentInfo.TvdbId.Should().Be(0); - torrentInfo.TvRageId.Should().Be(0); - torrentInfo.MagnetUrl.Should().BeNullOrEmpty(); - torrentInfo.Peers.Should().Be(2+5); - torrentInfo.Seeders.Should().Be(2); - } - - private void VerifyBackOff() - { - Mocker.GetMock() - .Verify(v => v.RecordFailure(It.IsAny(), It.IsAny()), Times.Once()); - } - - [Test] - public void should_back_off_on_bad_request() - { - Mocker.GetMock() - .Setup(v => v.Execute(It.IsAny())) - .Returns(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.BadRequest)); - - var results = Subject.FetchRecent(); - - results.Should().BeEmpty(); - - VerifyBackOff(); - - ExceptionVerification.ExpectedWarns(1); - } - - [Test] - public void should_back_off_and_report_api_key_invalid() - { - Mocker.GetMock() - .Setup(v => v.Execute(It.IsAny())) - .Returns(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.Unauthorized)); - - var results = Subject.FetchRecent(); - - results.Should().BeEmpty(); - - results.Should().BeEmpty(); - - VerifyBackOff(); - - ExceptionVerification.ExpectedWarns(1); - } - - [Test] - public void should_back_off_on_unknown_method() - { - Mocker.GetMock() - .Setup(v => v.Execute(It.IsAny())) - .Returns(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.NotFound)); - - var results = Subject.FetchRecent(); - - results.Should().BeEmpty(); - - VerifyBackOff(); - - ExceptionVerification.ExpectedWarns(1); - } - - [Test] - public void should_back_off_api_limit_reached() - { - Mocker.GetMock() - .Setup(v => v.Execute(It.IsAny())) - .Returns(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.ServiceUnavailable)); - - var results = Subject.FetchRecent(); - - results.Should().BeEmpty(); - - VerifyBackOff(); - - ExceptionVerification.ExpectedWarns(1); - } - - [Test] - public void should_replace_https_http_as_needed() - { - var recentFeed = ReadAllText(@"Files/Indexers/TitansOfTv/RecentFeed.json"); - - (Subject.Definition.Settings as TitansOfTvSettings).BaseUrl = "http://titansof.tv/api/torrents"; - - recentFeed = recentFeed.Replace("http:", "https:"); - - Mocker.GetMock() - .Setup(o => o.Execute(It.Is(v => v.Method == HttpMethod.GET))) - .Returns(r => new HttpResponse(r, new HttpHeader(), recentFeed)); - - var releases = Subject.FetchRecent(); - - releases.Should().HaveCount(2); - releases.First().Should().BeOfType(); - - var torrentInfo = releases.First() as TorrentInfo; - - torrentInfo.DownloadUrl.Should().Be("http://titansof.tv/api/torrents/19445/download?apikey=abc"); - torrentInfo.InfoUrl.Should().Be("http://titansof.tv/series/287053/episode/5453241"); - } - } -} diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 1eaf23bd5..9b476479b 100644 --- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -223,7 +223,6 @@ - @@ -509,9 +508,6 @@ - - Always - Always diff --git a/src/NzbDrone.Core/Datastore/Migration/098_remove_titans_of_tv.cs b/src/NzbDrone.Core/Datastore/Migration/098_remove_titans_of_tv.cs new file mode 100644 index 000000000..86b2eba1e --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/098_remove_titans_of_tv.cs @@ -0,0 +1,14 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(98)] + public class remove_titans_of_tv : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Delete.FromTable("Indexers").Row(new { Implementation = "TitansOfTv" }); + } + } +} diff --git a/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTv.cs b/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTv.cs deleted file mode 100644 index 0cb780f51..000000000 --- a/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTv.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using NLog; -using NzbDrone.Common.Http; -using NzbDrone.Core.Configuration; -using NzbDrone.Core.Parser; - -namespace NzbDrone.Core.Indexers.TitansOfTv -{ - public class TitansOfTv : HttpIndexerBase - { - 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"; } - } - - 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, PageSize = PageSize }; - } - - public override IParseIndexerResponse GetParser() - { - return new TitansOfTvParser(); - } - } -} diff --git a/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvApiResult.cs b/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvApiResult.cs deleted file mode 100644 index d2ecf46bd..000000000 --- a/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvApiResult.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace NzbDrone.Core.Indexers.TitansOfTv -{ - 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 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 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; } - public string codec { get; set; } - public string source { get; set; } - public string resolution { get; set; } - public string origin { get; set; } - public string language { get; set; } - public string release_name { get; set; } - public string tracker_updated_at { get; set; } - public DateTime created_at { get; set; } - public DateTime updated_at { get; set; } - public string season { get; set; } - 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 string commentUrl { get; set; } - } -} diff --git a/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvParser.cs b/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvParser.cs deleted file mode 100644 index a0ba04ba7..000000000 --- a/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvParser.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Collections.Generic; -using System.Net; -using System.Text.RegularExpressions; -using NzbDrone.Common.Extensions; -using NzbDrone.Common.Serializer; -using NzbDrone.Core.Indexers.Exceptions; -using NzbDrone.Core.Parser.Model; - -namespace NzbDrone.Core.Indexers.TitansOfTv -{ - public class TitansOfTvParser : IParseIndexerResponse - { - private static readonly Regex RegexProtocol = new Regex("^https?:", RegexOptions.Compiled); - - public IList ParseResponse(IndexerResponse indexerResponse) - { - var results = new List(); - - switch (indexerResponse.HttpResponse.StatusCode) - { - case HttpStatusCode.Unauthorized: - throw new ApiKeyException("API Key invalid or not authorized"); - case HttpStatusCode.NotFound: - throw new IndexerException(indexerResponse, "Indexer API call returned NotFound, the Indexer API may have changed."); - case HttpStatusCode.ServiceUnavailable: - throw new RequestLimitReachedException("Indexer API is temporarily unavailable, try again later"); - default: - if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK) - { - throw new IndexerException(indexerResponse, "Indexer API call returned an unexpected StatusCode [{0}]", indexerResponse.HttpResponse.StatusCode); - } - break; - } - - var content = indexerResponse.HttpResponse.Content; - var parsed = Json.Deserialize(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.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 = parsedItem.size; - release.Seeders = parsedItem.seeders; - release.Peers = parsedItem.leechers + release.Seeders; - release.PublishDate = parsedItem.created_at; - results.Add(release); - } - - return results; - } - } -} diff --git a/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvRequestGenerator.cs b/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvRequestGenerator.cs deleted file mode 100644 index fc88432db..000000000 --- a/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvRequestGenerator.cs +++ /dev/null @@ -1,121 +0,0 @@ -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 virtual IndexerPageableRequestChain GetRecentRequests() - { - var pageableRequests = new IndexerPageableRequestChain(); - - pageableRequests.Add(GetPagedRequests(MaxPages)); - - return pageableRequests; - } - - public virtual IndexerPageableRequestChain GetSearchRequests(SingleEpisodeSearchCriteria searchCriteria) - { - var pageableRequests = new IndexerPageableRequestChain(); - - pageableRequests.Add(GetPagedRequests(MaxPages, - series_id: searchCriteria.Series.TvdbId, - episode: string.Format("S{0:00}E{1:00}", searchCriteria.SeasonNumber, searchCriteria.EpisodeNumber))); - - pageableRequests.Add(GetPagedRequests(MaxPages, - series_id: searchCriteria.Series.TvdbId, - season: string.Format("Season {0:00}", searchCriteria.SeasonNumber))); - - return pageableRequests; - } - - public virtual IndexerPageableRequestChain GetSearchRequests(SeasonSearchCriteria searchCriteria) - { - var pageableRequests = new IndexerPageableRequestChain(); - - pageableRequests.Add(GetPagedRequests(MaxPages, - series_id: searchCriteria.Series.TvdbId, - season: string.Format("Season {0:00}", searchCriteria.SeasonNumber))); - - pageableRequests.AddTier(); - - // TODO: Search for all episodes?!? - - return pageableRequests; - } - - public virtual IndexerPageableRequestChain GetSearchRequests(DailyEpisodeSearchCriteria searchCriteria) - { - var pageableRequests = new IndexerPageableRequestChain(); - - pageableRequests.Add(GetPagedRequests(MaxPages, - series_id: searchCriteria.Series.TvdbId, - air_date: searchCriteria.AirDate)); - - return pageableRequests; - } - - public virtual IndexerPageableRequestChain GetSearchRequests(AnimeEpisodeSearchCriteria searchCriteria) - { - return new IndexerPageableRequestChain(); - } - - public virtual IndexerPageableRequestChain GetSearchRequests(SpecialEpisodeSearchCriteria searchCriteria) - { - return new IndexerPageableRequestChain(); - } - - private IEnumerable GetPagedRequests(int maxPages, int? series_id = null, string episode = null, string season = null, DateTime? air_date = null) - { - 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; - } - } - } -} diff --git a/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvSettings.cs b/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvSettings.cs deleted file mode 100644 index 013db49a7..000000000 --- a/src/NzbDrone.Core/Indexers/TitansOfTv/TitansOfTvSettings.cs +++ /dev/null @@ -1,36 +0,0 @@ -using FluentValidation; -using NzbDrone.Core.Annotations; -using NzbDrone.Core.ThingiProvider; -using NzbDrone.Core.Validation; - -namespace NzbDrone.Core.Indexers.TitansOfTv -{ - public class TitansOfTvSettingsValidator : AbstractValidator - { - public TitansOfTvSettingsValidator() - { - RuleFor(c => c.ApiKey).NotEmpty(); - } - } - - public class TitansOfTvSettings : IProviderConfig - { - private static readonly TitansOfTvSettingsValidator Validator = new TitansOfTvSettingsValidator(); - - public TitansOfTvSettings() - { - 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.")] - public string BaseUrl { get; set; } - - [FieldDefinition(1, Label = "API key", HelpText = "Enter your ToTV API key. (My Account->API->Site API Key)")] - public string ApiKey { get; set; } - - public NzbDroneValidationResult Validate() - { - return new NzbDroneValidationResult(Validator.Validate(this)); - } - } -} diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 2d2435cc9..414dbc05d 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -273,6 +273,9 @@ + + Code + @@ -554,11 +557,6 @@ - - - - -