Added TorrentPotato Indexer.

This commit is contained in:
Leonardo Galli 2017-01-05 17:12:46 +01:00
parent a63587bb19
commit 7a5fe59dbf
7 changed files with 321 additions and 0 deletions

View File

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Exceptions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Http.CloudFlare;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.TorrentPotato
{
public class TorrentPotato : HttpIndexerBase<TorrentPotatoSettings>
{
public override string Name => "TorrentPotato";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override TimeSpan RateLimit => TimeSpan.FromSeconds(2);
public TorrentPotato(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
: base(httpClient, indexerStatusService, configService, parsingService, logger)
{
}
public override IEnumerable<ProviderDefinition> DefaultDefinitions
{
get
{
yield return GetDefinition("Jackett", new TorrentPotatoSettings { BaseUrl = "http://localhost:9117/potato/YOURINDEXER"});
}
}
private IndexerDefinition GetDefinition(string name, TorrentPotatoSettings settings)
{
return new IndexerDefinition
{
EnableRss = false,
EnableSearch = false,
Name = name,
Implementation = GetType().Name,
Settings = settings,
Protocol = DownloadProtocol.Torrent,
SupportsRss = SupportsRss,
SupportsSearch = SupportsSearch
};
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new TorrentPotatoRequestGenerator() { Settings = Settings };
}
public override IParseIndexerResponse GetParser()
{
return new TorrentPotatoParser();
}
}
}

View File

@ -0,0 +1,65 @@
using System.Collections.Generic;
using System.Net;
using System.Text.RegularExpressions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Indexers.TorrentPotato
{
public class TorrentPotatoParser : IParseIndexerResponse
{
private static readonly Regex RegexGuid = new Regex(@"^magnet:\?xt=urn:btih:([a-f0-9]+)", RegexOptions.Compiled);
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var results = new List<ReleaseInfo>();
switch (indexerResponse.HttpResponse.StatusCode)
{
default:
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
{
throw new IndexerException(indexerResponse, "Indexer API call returned an unexpected StatusCode [{0}]", indexerResponse.HttpResponse.StatusCode);
}
break;
}
var jsonResponse = new HttpResponse<TorrentPotatoResponse>(indexerResponse.HttpResponse);
foreach (var torrent in jsonResponse.Resource.results)
{
var torrentInfo = new TorrentInfo();
torrentInfo.Guid = GetGuid(torrent);
torrentInfo.Title = torrent.release_name;
torrentInfo.Size = (long)torrent.size*1000*1000;
torrentInfo.DownloadUrl = torrent.download_url;
torrentInfo.InfoUrl = torrent.details_url;
torrentInfo.PublishDate = new System.DateTime();
torrentInfo.Seeders = torrent.seeders;
torrentInfo.Peers = torrent.leechers + torrent.seeders;
torrentInfo.Freeleech = torrent.freeleech;
results.Add(torrentInfo);
}
return results;
}
private string GetGuid(Result torrent)
{
var match = RegexGuid.Match(torrent.download_url);
if (match.Success)
{
return string.Format("potato-{0}", match.Groups[1].Value);
}
else
{
return string.Format("potato-{0}", torrent.download_url);
}
}
}
}

View File

@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.IndexerSearch.Definitions;
namespace NzbDrone.Core.Indexers.TorrentPotato
{
public class TorrentPotatoRequestGenerator : IIndexerRequestGenerator
{
public TorrentPotatoSettings Settings { get; set; }
public TorrentPotatoRequestGenerator()
{
}
public virtual IndexerPageableRequestChain GetRecentRequests()
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests("list", null, null));
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(SingleEpisodeSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests("search", searchCriteria.Series.TvdbId, "S{0:00}E{1:00}", searchCriteria.SeasonNumber, searchCriteria.EpisodeNumber));
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(SeasonSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests("search", searchCriteria.Series.TvdbId, "S{0:00}", searchCriteria.SeasonNumber));
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(DailyEpisodeSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests("search", searchCriteria.Series.TvdbId, "\"{0:yyyy MM dd}\"", searchCriteria.AirDate));
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(AnimeEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(SpecialEpisodeSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
foreach (var queryTitle in searchCriteria.EpisodeQueryTitles)
{
var query = queryTitle.Replace('+', ' ');
query = System.Web.HttpUtility.UrlEncode(query);
pageableRequests.Add(GetPagedRequests("search", searchCriteria.Series.TvdbId, query));
}
return pageableRequests;
}
private IEnumerable<IndexerRequest> GetPagedRequests(string mode, int? tvdbId, string query, params object[] args)
{
var requestBuilder = new HttpRequestBuilder(Settings.BaseUrl)
.Accept(HttpAccept.Json);
requestBuilder.AddQueryParam("passkey", Settings.Passkey);
requestBuilder.AddQueryParam("user", Settings.User);
requestBuilder.AddQueryParam("imdbid", "tt0076759"); //For now just search for Star Wars.
yield return new IndexerRequest(requestBuilder.Build());
}
private IEnumerable<IndexerRequest> GetMovieRequest(MovieSearchCriteria searchCriteria)
{
var requestBuilder = new HttpRequestBuilder(Settings.BaseUrl)
.Accept(HttpAccept.Json);
requestBuilder.AddQueryParam("passkey", Settings.Passkey);
requestBuilder.AddQueryParam("user", Settings.User);
if (searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace())
{
requestBuilder.AddQueryParam("imdbid", searchCriteria.Movie.ImdbId);
}
else
{
requestBuilder.AddQueryParam("search", searchCriteria.Movie.Title);
}
yield return new IndexerRequest(requestBuilder.Build());
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetMovieRequest(searchCriteria));
return pageableRequests;
}
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
namespace NzbDrone.Core.Indexers.TorrentPotato
{
public class TorrentPotatoResponse
{
public Result[] results { get; set; }
public int total_results { get; set; }
}
public class Result
{
public string release_name { get; set; }
public string torrent_id { get; set; }
public string details_url { get; set; }
public string download_url { get; set; }
public bool freeleech { get; set; }
public string type { get; set; }
public int size { get; set; }
public int leechers { get; set; }
public int seeders { get; set; }
}
}

View File

@ -0,0 +1,38 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.TorrentPotato
{
public class TorrentPotatoSettingsValidator : AbstractValidator<TorrentPotatoSettings>
{
public TorrentPotatoSettingsValidator()
{
RuleFor(c => c.BaseUrl).ValidRootUrl();
}
}
public class TorrentPotatoSettings : IProviderConfig
{
private static readonly TorrentPotatoSettingsValidator Validator = new TorrentPotatoSettingsValidator();
public TorrentPotatoSettings()
{
BaseUrl = "";
}
[FieldDefinition(0, Label = "API URL", HelpText = "URL to TorrentPotato api.")]
public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "Username", HelpText = "The username you use at your indexer.")]
public string User { get; set; }
[FieldDefinition(2, Label = "Passkey", HelpText = "The password you use at your Indexer,")]
public string Passkey { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@ -633,6 +633,11 @@
<Compile Include="Indexers\Omgwtfnzbs\OmgwtfnzbsRssParser.cs" />
<Compile Include="Indexers\Omgwtfnzbs\OmgwtfnzbsSettings.cs" />
<Compile Include="Indexers\HttpIndexerBase.cs" />
<Compile Include="Indexers\TorrentPotato\TorrentPotato.cs" />
<Compile Include="Indexers\TorrentPotato\TorrentPotatoParser.cs" />
<Compile Include="Indexers\TorrentPotato\TorrentPotatoRequestGenerator.cs" />
<Compile Include="Indexers\TorrentPotato\TorrentPotatoResponse.cs" />
<Compile Include="Indexers\TorrentPotato\TorrentPotatoSettings.cs" />
<Compile Include="Indexers\Rarbg\Rarbg.cs" />
<Compile Include="Indexers\Rarbg\RarbgRequestGenerator.cs" />
<Compile Include="Indexers\Rarbg\RarbgResponse.cs" />

View File

@ -8,6 +8,7 @@ namespace NzbDrone.Core.Parser.Model
public string InfoHash { get; set; }
public int? Seeders { get; set; }
public int? Peers { get; set; }
public bool Freeleech { get; set; }
public static int? GetSeeders(ReleaseInfo release)
{