mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-09-27 20:44:00 +02:00
Fixed: (TorrentPotato) Allow use of custom APIs
This commit is contained in:
@@ -1,32 +1,51 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
||||||
{
|
{
|
||||||
public class TorrentPotato : TorrentIndexerBase<TorrentPotatoSettings>
|
public class TorrentPotato : TorrentIndexerBase<TorrentPotatoSettings>
|
||||||
{
|
{
|
||||||
public override string Name => "TorrentPotato";
|
public override string Name => "TorrentPotato";
|
||||||
public override string[] IndexerUrls => new[] { "http://127.0.0.1" };
|
public override string[] IndexerUrls => new[] { "" };
|
||||||
public override string Description => "A JSON based torrent provider previously developed for CouchPotato";
|
public override string Description => "A JSON based torrent provider previously developed for CouchPotato";
|
||||||
|
|
||||||
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
|
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
|
||||||
public override TimeSpan RateLimit => TimeSpan.FromSeconds(2);
|
public override IndexerCapabilities Capabilities => SetCapabilities();
|
||||||
|
|
||||||
public TorrentPotato(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
|
public TorrentPotato(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
|
||||||
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
|
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private IndexerDefinition GetDefinition(string name, TorrentPotatoSettings settings)
|
public override IIndexerRequestGenerator GetRequestGenerator()
|
||||||
|
{
|
||||||
|
return new TorrentPotatoRequestGenerator(Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IParseIndexerResponse GetParser()
|
||||||
|
{
|
||||||
|
return new TorrentPotatoParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<ProviderDefinition> DefaultDefinitions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
yield return GetDefinition("TorrentPotato", "A JSON based torrent provider previously developed for CouchPotato", "http://127.0.0.1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IndexerDefinition GetDefinition(string name, string description, string baseUrl)
|
||||||
{
|
{
|
||||||
return new IndexerDefinition
|
return new IndexerDefinition
|
||||||
{
|
{
|
||||||
Enable = true,
|
Enable = true,
|
||||||
Name = name,
|
Name = name,
|
||||||
|
Description = description,
|
||||||
Implementation = GetType().Name,
|
Implementation = GetType().Name,
|
||||||
Settings = settings,
|
Settings = new TorrentPotatoSettings { BaseUrl = baseUrl },
|
||||||
Protocol = DownloadProtocol.Torrent,
|
Protocol = DownloadProtocol.Torrent,
|
||||||
SupportsRss = SupportsRss,
|
SupportsRss = SupportsRss,
|
||||||
SupportsSearch = SupportsSearch,
|
SupportsSearch = SupportsSearch,
|
||||||
@@ -35,14 +54,19 @@ namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IIndexerRequestGenerator GetRequestGenerator()
|
private IndexerCapabilities SetCapabilities()
|
||||||
{
|
{
|
||||||
return new TorrentPotatoRequestGenerator() { Settings = Settings };
|
var caps = new IndexerCapabilities
|
||||||
|
{
|
||||||
|
MovieSearchParams = new List<MovieSearchParam>
|
||||||
|
{
|
||||||
|
MovieSearchParam.Q, MovieSearchParam.ImdbId
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public override IParseIndexerResponse GetParser()
|
caps.Categories.AddCategoryMapping("1", NewznabStandardCategory.Movies);
|
||||||
{
|
|
||||||
return new TorrentPotatoParser();
|
return caps;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,33 +1,39 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Indexers.Exceptions;
|
using NzbDrone.Core.Indexers.Exceptions;
|
||||||
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
||||||
{
|
{
|
||||||
public class TorrentPotatoParser : IParseIndexerResponse
|
public class TorrentPotatoParser : IParseIndexerResponse
|
||||||
{
|
{
|
||||||
private static readonly Regex RegexGuid = new Regex(@"^magnet:\?xt=urn:btih:([a-f0-9]+)", RegexOptions.Compiled);
|
private static readonly Regex RegexGuid = new (@"^magnet:\?xt=urn:btih:([a-f0-9]+)", RegexOptions.Compiled);
|
||||||
|
|
||||||
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||||
{
|
{
|
||||||
var results = new List<ReleaseInfo>();
|
var releaseInfos = new List<ReleaseInfo>();
|
||||||
|
|
||||||
switch (indexerResponse.HttpResponse.StatusCode)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
|
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
|
||||||
{
|
{
|
||||||
throw new IndexerException(indexerResponse, "Indexer API call returned an unexpected StatusCode [{0}]", indexerResponse.HttpResponse.StatusCode);
|
throw new IndexerException(indexerResponse, "Indexer API call returned an unexpected StatusCode [{0}]", indexerResponse.HttpResponse.StatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
var jsonResponse = new HttpResponse<TorrentPotatoResponse>(indexerResponse.HttpResponse);
|
||||||
|
|
||||||
|
if (jsonResponse.Resource?.error != null)
|
||||||
|
{
|
||||||
|
throw new IndexerException(indexerResponse, "Indexer API call returned an error [{0}]", jsonResponse.Resource.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
var jsonResponse = new HttpResponse<TorrentPotatoResponse>(indexerResponse.HttpResponse);
|
if (jsonResponse.Resource?.results == null)
|
||||||
|
{
|
||||||
|
return releaseInfos;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var torrent in jsonResponse.Resource.results)
|
foreach (var torrent in jsonResponse.Resource.results)
|
||||||
{
|
{
|
||||||
@@ -35,18 +41,22 @@ namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
|||||||
{
|
{
|
||||||
Guid = GetGuid(torrent),
|
Guid = GetGuid(torrent),
|
||||||
Title = torrent.release_name,
|
Title = torrent.release_name,
|
||||||
Size = (long)torrent.size * 1000 * 1000,
|
Categories = new List<IndexerCategory> { NewznabStandardCategory.Movies },
|
||||||
|
Size = torrent.size * 1000 * 1000,
|
||||||
DownloadUrl = torrent.download_url,
|
DownloadUrl = torrent.download_url,
|
||||||
InfoUrl = torrent.details_url,
|
InfoUrl = torrent.details_url,
|
||||||
|
ImdbId = ParseUtil.GetImdbId(torrent.imdb_id).GetValueOrDefault(),
|
||||||
PublishDate = torrent.publish_date.ToUniversalTime(),
|
PublishDate = torrent.publish_date.ToUniversalTime(),
|
||||||
Seeders = torrent.seeders,
|
Seeders = torrent.seeders,
|
||||||
Peers = torrent.leechers + torrent.seeders
|
Peers = torrent.leechers + torrent.seeders
|
||||||
};
|
};
|
||||||
|
|
||||||
results.Add(torrentInfo);
|
releaseInfos.Add(torrentInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return releaseInfos
|
||||||
|
.OrderByDescending(o => o.PublishDate)
|
||||||
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||||
@@ -57,12 +67,10 @@ namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
|||||||
|
|
||||||
if (match.Success)
|
if (match.Success)
|
||||||
{
|
{
|
||||||
return string.Format("potato-{0}", match.Groups[1].Value);
|
return $"potato-{match.Groups[1].Value}";
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return string.Format("potato-{0}", torrent.download_url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $"potato-{torrent.download_url}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,70 +8,19 @@ namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
|||||||
{
|
{
|
||||||
public class TorrentPotatoRequestGenerator : IIndexerRequestGenerator
|
public class TorrentPotatoRequestGenerator : IIndexerRequestGenerator
|
||||||
{
|
{
|
||||||
public TorrentPotatoSettings Settings { get; set; }
|
private readonly TorrentPotatoSettings _settings;
|
||||||
|
|
||||||
public virtual IndexerPageableRequestChain GetRecentRequests()
|
public TorrentPotatoRequestGenerator(TorrentPotatoSettings settings)
|
||||||
{
|
{
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
_settings = settings;
|
||||||
|
|
||||||
pageableRequests.Add(GetPagedRequests("list", null, null));
|
|
||||||
|
|
||||||
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);
|
|
||||||
if (!string.IsNullOrWhiteSpace(Settings.User))
|
|
||||||
{
|
|
||||||
requestBuilder.AddQueryParam("user", Settings.User);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
requestBuilder.AddQueryParam("user", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
requestBuilder.AddQueryParam("search", "-");
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(Settings.User))
|
|
||||||
{
|
|
||||||
requestBuilder.AddQueryParam("user", Settings.User);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
requestBuilder.AddQueryParam("user", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchCriteria.ImdbId.IsNotNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
requestBuilder.AddQueryParam("imdbid", searchCriteria.ImdbId);
|
|
||||||
}
|
|
||||||
else if (searchCriteria.SearchTerm.IsNotNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
//TODO: Hack for now
|
|
||||||
requestBuilder.AddQueryParam("search", $"{searchCriteria.SearchTerm}");
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return new IndexerRequest(requestBuilder.Build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
||||||
{
|
{
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
var pageableRequests = new IndexerPageableRequestChain();
|
||||||
pageableRequests.Add(GetMovieRequest(searchCriteria));
|
|
||||||
|
pageableRequests.Add(BuildRequest(searchCriteria.SearchTerm, searchCriteria.ImdbId));
|
||||||
|
|
||||||
return pageableRequests;
|
return pageableRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +41,29 @@ namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
|||||||
|
|
||||||
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
|
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
|
||||||
{
|
{
|
||||||
return new IndexerPageableRequestChain();
|
var pageableRequests = new IndexerPageableRequestChain();
|
||||||
|
|
||||||
|
pageableRequests.Add(BuildRequest(searchCriteria.SearchTerm));
|
||||||
|
|
||||||
|
return pageableRequests;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<IndexerRequest> BuildRequest(string searchTerm, string imdbId = null)
|
||||||
|
{
|
||||||
|
var requestBuilder = new HttpRequestBuilder(_settings.BaseUrl)
|
||||||
|
.Accept(HttpAccept.Json);
|
||||||
|
|
||||||
|
requestBuilder.AddQueryParam("passkey", _settings.Passkey);
|
||||||
|
requestBuilder.AddQueryParam("user", _settings.User.IsNotNullOrWhiteSpace() ? _settings.User : "");
|
||||||
|
|
||||||
|
if (imdbId.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
requestBuilder.AddQueryParam("imdbid", imdbId);
|
||||||
|
}
|
||||||
|
|
||||||
|
requestBuilder.AddQueryParam("search", searchTerm.IsNotNullOrWhiteSpace() ? $"{searchTerm}" : " ");
|
||||||
|
|
||||||
|
yield return new IndexerRequest(requestBuilder.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<IDictionary<string, string>> GetCookies { get; set; }
|
public Func<IDictionary<string, string>> GetCookies { get; set; }
|
||||||
|
@@ -4,8 +4,9 @@ namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
|||||||
{
|
{
|
||||||
public class TorrentPotatoResponse
|
public class TorrentPotatoResponse
|
||||||
{
|
{
|
||||||
public Result[] results { get; set; }
|
|
||||||
public int total_results { get; set; }
|
public int total_results { get; set; }
|
||||||
|
public Result[] results { get; set; }
|
||||||
|
public string error { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Result
|
public class Result
|
||||||
@@ -14,9 +15,10 @@ namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
|||||||
public string torrent_id { get; set; }
|
public string torrent_id { get; set; }
|
||||||
public string details_url { get; set; }
|
public string details_url { get; set; }
|
||||||
public string download_url { get; set; }
|
public string download_url { get; set; }
|
||||||
|
public string imdb_id { get; set; }
|
||||||
public bool freeleech { get; set; }
|
public bool freeleech { get; set; }
|
||||||
public string type { get; set; }
|
public string type { get; set; }
|
||||||
public int size { get; set; }
|
public long size { get; set; }
|
||||||
public int leechers { get; set; }
|
public int leechers { get; set; }
|
||||||
public int seeders { get; set; }
|
public int seeders { get; set; }
|
||||||
public DateTime publish_date { get; set; }
|
public DateTime publish_date { get; set; }
|
||||||
|
@@ -1,30 +1,42 @@
|
|||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
using NzbDrone.Core.Indexers.Settings;
|
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
||||||
{
|
{
|
||||||
public class TorrentPotatoSettingsValidator : NoAuthSettingsValidator<TorrentPotatoSettings>
|
public class TorrentPotatoSettingsValidator : AbstractValidator<TorrentPotatoSettings>
|
||||||
{
|
{
|
||||||
public TorrentPotatoSettingsValidator()
|
public TorrentPotatoSettingsValidator()
|
||||||
{
|
{
|
||||||
RuleFor(c => c.User).NotEmpty();
|
RuleFor(c => c.User).NotEmpty();
|
||||||
RuleFor(c => c.Passkey).NotEmpty();
|
RuleFor(c => c.Passkey).NotEmpty();
|
||||||
|
|
||||||
|
RuleFor(c => c.BaseUrl).ValidRootUrl();
|
||||||
|
RuleFor(c => c.BaseSettings).SetValidator(new IndexerCommonSettingsValidator());
|
||||||
|
RuleFor(c => c.TorrentBaseSettings).SetValidator(new IndexerTorrentSettingsValidator());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TorrentPotatoSettings : NoAuthTorrentBaseSettings
|
public class TorrentPotatoSettings : IIndexerSettings
|
||||||
{
|
{
|
||||||
private static readonly TorrentPotatoSettingsValidator Validator = new ();
|
private static readonly TorrentPotatoSettingsValidator Validator = new ();
|
||||||
|
|
||||||
|
[FieldDefinition(0, Label = "API URL", HelpText = "URL to TorrentPotato API")]
|
||||||
|
public string BaseUrl { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(2, Label = "Username", HelpText = "Indexer Username", Privacy = PrivacyLevel.UserName)]
|
[FieldDefinition(2, Label = "Username", HelpText = "Indexer Username", Privacy = PrivacyLevel.UserName)]
|
||||||
public string User { get; set; }
|
public string User { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(3, Label = "Passkey", HelpText = "Indexer Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
|
[FieldDefinition(3, Label = "Passkey", HelpText = "Indexer Passkey", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
|
||||||
public string Passkey { get; set; }
|
public string Passkey { get; set; }
|
||||||
|
|
||||||
public override NzbDroneValidationResult Validate()
|
[FieldDefinition(20)]
|
||||||
|
public IndexerBaseSettings BaseSettings { get; set; } = new ();
|
||||||
|
|
||||||
|
[FieldDefinition(21)]
|
||||||
|
public IndexerTorrentBaseSettings TorrentBaseSettings { get; set; } = new ();
|
||||||
|
|
||||||
|
public virtual NzbDroneValidationResult Validate()
|
||||||
{
|
{
|
||||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user