mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-04-24 13:57:11 -04:00
Fixed: (TorrentPotato) Allow use of custom APIs
This commit is contained in:
parent
90e92c0b66
commit
6769055b6b
5 changed files with 112 additions and 95 deletions
|
@ -1,32 +1,51 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
||||
{
|
||||
public class TorrentPotato : TorrentIndexerBase<TorrentPotatoSettings>
|
||||
{
|
||||
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 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)
|
||||
: 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
|
||||
{
|
||||
Enable = true,
|
||||
Name = name,
|
||||
Description = description,
|
||||
Implementation = GetType().Name,
|
||||
Settings = settings,
|
||||
Settings = new TorrentPotatoSettings { BaseUrl = baseUrl },
|
||||
Protocol = DownloadProtocol.Torrent,
|
||||
SupportsRss = SupportsRss,
|
||||
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()
|
||||
{
|
||||
return new TorrentPotatoParser();
|
||||
caps.Categories.AddCategoryMapping("1", NewznabStandardCategory.Movies);
|
||||
|
||||
return caps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,52 +1,62 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers.Exceptions;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
||||
{
|
||||
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)
|
||||
{
|
||||
var results = new List<ReleaseInfo>();
|
||||
var releaseInfos = new List<ReleaseInfo>();
|
||||
|
||||
switch (indexerResponse.HttpResponse.StatusCode)
|
||||
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
default:
|
||||
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new IndexerException(indexerResponse, "Indexer API call returned an unexpected StatusCode [{0}]", indexerResponse.HttpResponse.StatusCode);
|
||||
}
|
||||
|
||||
break;
|
||||
throw new IndexerException(indexerResponse, "Indexer API call returned an unexpected StatusCode [{0}]", indexerResponse.HttpResponse.StatusCode);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (jsonResponse.Resource?.results == null)
|
||||
{
|
||||
return releaseInfos;
|
||||
}
|
||||
|
||||
foreach (var torrent in jsonResponse.Resource.results)
|
||||
{
|
||||
var torrentInfo = new TorrentInfo
|
||||
{
|
||||
Guid = GetGuid(torrent),
|
||||
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,
|
||||
InfoUrl = torrent.details_url,
|
||||
ImdbId = ParseUtil.GetImdbId(torrent.imdb_id).GetValueOrDefault(),
|
||||
PublishDate = torrent.publish_date.ToUniversalTime(),
|
||||
Seeders = 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; }
|
||||
|
@ -57,12 +67,10 @@ namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
|||
|
||||
if (match.Success)
|
||||
{
|
||||
return string.Format("potato-{0}", match.Groups[1].Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Format("potato-{0}", torrent.download_url);
|
||||
return $"potato-{match.Groups[1].Value}";
|
||||
}
|
||||
|
||||
return $"potato-{torrent.download_url}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,70 +8,19 @@ namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
|||
{
|
||||
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();
|
||||
|
||||
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());
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
||||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
pageableRequests.Add(GetMovieRequest(searchCriteria));
|
||||
|
||||
pageableRequests.Add(BuildRequest(searchCriteria.SearchTerm, searchCriteria.ImdbId));
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
|
@ -92,7 +41,29 @@ namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
|||
|
||||
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; }
|
||||
|
|
|
@ -4,8 +4,9 @@ namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
|||
{
|
||||
public class TorrentPotatoResponse
|
||||
{
|
||||
public Result[] results { get; set; }
|
||||
public int total_results { get; set; }
|
||||
public Result[] results { get; set; }
|
||||
public string error { get; set; }
|
||||
}
|
||||
|
||||
public class Result
|
||||
|
@ -14,9 +15,10 @@ namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
|||
public string torrent_id { get; set; }
|
||||
public string details_url { get; set; }
|
||||
public string download_url { get; set; }
|
||||
public string imdb_id { get; set; }
|
||||
public bool freeleech { get; set; }
|
||||
public string type { get; set; }
|
||||
public int size { get; set; }
|
||||
public long size { get; set; }
|
||||
public int leechers { get; set; }
|
||||
public int seeders { get; set; }
|
||||
public DateTime publish_date { get; set; }
|
||||
|
|
|
@ -1,30 +1,42 @@
|
|||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Indexers.Settings;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.Definitions.TorrentPotato
|
||||
{
|
||||
public class TorrentPotatoSettingsValidator : NoAuthSettingsValidator<TorrentPotatoSettings>
|
||||
public class TorrentPotatoSettingsValidator : AbstractValidator<TorrentPotatoSettings>
|
||||
{
|
||||
public TorrentPotatoSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.User).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 ();
|
||||
|
||||
[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)]
|
||||
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 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));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue