mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2026-04-26 23:06:43 -04:00
Cleanup Search UI, Newznab Caps API
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.HDBits
|
||||
{
|
||||
public class HDBits : HttpIndexerBase<HDBitsSettings>
|
||||
{
|
||||
public override string Name => "HDBits";
|
||||
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
|
||||
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
|
||||
|
||||
public override int PageSize => 30;
|
||||
|
||||
public HDBits(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
|
||||
: base(httpClient, indexerStatusService, configService, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override IIndexerRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
return new HDBitsRequestGenerator() { Settings = Settings };
|
||||
}
|
||||
|
||||
public override IParseIndexerResponse GetParser()
|
||||
{
|
||||
return new HDBitsParser(Settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.HDBits
|
||||
{
|
||||
public class TorrentQuery
|
||||
{
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public string Username { get; set; }
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public string Passkey { get; set; }
|
||||
|
||||
public string Hash { get; set; }
|
||||
|
||||
public string Search { get; set; }
|
||||
|
||||
public int[] Category { get; set; }
|
||||
|
||||
public int[] Codec { get; set; }
|
||||
|
||||
public int[] Medium { get; set; }
|
||||
|
||||
public int? Origin { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "imdb")]
|
||||
public ImdbInfo ImdbInfo { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "tvdb")]
|
||||
public TvdbInfo TvdbInfo { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "file_in_torrent")]
|
||||
public string FileInTorrent { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "snatched_only")]
|
||||
public bool? SnatchedOnly { get; set; }
|
||||
public int? Limit { get; set; }
|
||||
public int? Page { get; set; }
|
||||
|
||||
public TorrentQuery Clone()
|
||||
{
|
||||
return MemberwiseClone() as TorrentQuery;
|
||||
}
|
||||
}
|
||||
|
||||
public class HDBitsResponse
|
||||
{
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public StatusCode Status { get; set; }
|
||||
public string Message { get; set; }
|
||||
public object Data { get; set; }
|
||||
}
|
||||
|
||||
public class TorrentQueryResponse
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Hash { get; set; }
|
||||
public int Leechers { get; set; }
|
||||
public int Seeders { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "times_completed")]
|
||||
|
||||
public uint TimesCompleted { get; set; }
|
||||
|
||||
public long Size { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "utadded")]
|
||||
public long UtAdded { get; set; }
|
||||
|
||||
public DateTime Added { get; set; }
|
||||
|
||||
public uint Comments { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "numfiles")]
|
||||
public uint NumFiles { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "filename")]
|
||||
public string FileName { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "freeleech")]
|
||||
public string FreeLeech { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "type_category")]
|
||||
public int TypeCategory { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "type_codec")]
|
||||
public int TypeCodec { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "type_medium")]
|
||||
public int TypeMedium { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "type_origin")]
|
||||
public int TypeOrigin { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "imdb")]
|
||||
public ImdbInfo ImdbInfo { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "tvdb")]
|
||||
public TvdbInfo TvdbInfo { get; set; }
|
||||
}
|
||||
|
||||
public class ImdbInfo
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string EnglishTitle { get; set; }
|
||||
public string OriginalTitle { get; set; }
|
||||
public int? Year { get; set; }
|
||||
public string[] Genres { get; set; }
|
||||
public float? Rating { get; set; }
|
||||
}
|
||||
|
||||
public class TvdbInfo
|
||||
{
|
||||
public int? Id { get; set; }
|
||||
public int? Season { get; set; }
|
||||
public int? Episode { get; set; }
|
||||
}
|
||||
|
||||
public enum StatusCode
|
||||
{
|
||||
Success = 0,
|
||||
Failure = 1,
|
||||
SslRequired = 2,
|
||||
JsonMalformed = 3,
|
||||
AuthDataMissing = 4,
|
||||
AuthFailed = 5,
|
||||
MissingRequiredParameters = 6,
|
||||
InvalidParameter = 7,
|
||||
ImdbImportFail = 8,
|
||||
ImdbTvNotAllowed = 9
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.HDBits
|
||||
{
|
||||
public class HDBitsInfo : TorrentInfo
|
||||
{
|
||||
public bool? Internal { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers.Exceptions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.HDBits
|
||||
{
|
||||
public class HDBitsParser : IParseIndexerResponse
|
||||
{
|
||||
private readonly HDBitsSettings _settings;
|
||||
|
||||
public HDBitsParser(HDBitsSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
{
|
||||
var torrentInfos = new List<ReleaseInfo>();
|
||||
|
||||
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new IndexerException(indexerResponse,
|
||||
"Unexpected response status {0} code from API request",
|
||||
indexerResponse.HttpResponse.StatusCode);
|
||||
}
|
||||
|
||||
var jsonResponse = JsonConvert.DeserializeObject<HDBitsResponse>(indexerResponse.Content);
|
||||
|
||||
if (jsonResponse.Status != StatusCode.Success)
|
||||
{
|
||||
throw new IndexerException(indexerResponse,
|
||||
"HDBits API request returned status code {0}: {1}",
|
||||
jsonResponse.Status,
|
||||
jsonResponse.Message ?? string.Empty);
|
||||
}
|
||||
|
||||
var responseData = jsonResponse.Data as JArray;
|
||||
if (responseData == null)
|
||||
{
|
||||
throw new IndexerException(indexerResponse,
|
||||
"Indexer API call response missing result data");
|
||||
}
|
||||
|
||||
var queryResults = responseData.ToObject<TorrentQueryResponse[]>();
|
||||
|
||||
foreach (var result in queryResults)
|
||||
{
|
||||
var id = result.Id;
|
||||
var internalRelease = result.TypeOrigin == 1 ? true : false;
|
||||
|
||||
IndexerFlags flags = 0;
|
||||
|
||||
if (result.FreeLeech == "yes")
|
||||
{
|
||||
flags |= IndexerFlags.G_Freeleech;
|
||||
}
|
||||
|
||||
if (internalRelease)
|
||||
{
|
||||
flags |= IndexerFlags.HDB_Internal;
|
||||
}
|
||||
|
||||
torrentInfos.Add(new HDBitsInfo()
|
||||
{
|
||||
Guid = string.Format("HDBits-{0}", id),
|
||||
Title = result.Name,
|
||||
Size = result.Size,
|
||||
InfoHash = result.Hash,
|
||||
DownloadUrl = GetDownloadUrl(id),
|
||||
InfoUrl = GetInfoUrl(id),
|
||||
Seeders = result.Seeders,
|
||||
Peers = result.Leechers + result.Seeders,
|
||||
PublishDate = result.Added.ToUniversalTime(),
|
||||
Internal = internalRelease,
|
||||
ImdbId = result.ImdbInfo?.Id ?? 0,
|
||||
IndexerFlags = flags
|
||||
});
|
||||
}
|
||||
|
||||
return torrentInfos.ToArray();
|
||||
}
|
||||
|
||||
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||
|
||||
private string GetDownloadUrl(string torrentId)
|
||||
{
|
||||
var url = new HttpUri(_settings.BaseUrl)
|
||||
.CombinePath("/download.php")
|
||||
.AddQueryParam("id", torrentId)
|
||||
.AddQueryParam("passkey", _settings.ApiKey);
|
||||
|
||||
return url.FullUri;
|
||||
}
|
||||
|
||||
private string GetInfoUrl(string torrentId)
|
||||
{
|
||||
var url = new HttpUri(_settings.BaseUrl)
|
||||
.CombinePath("/details.php")
|
||||
.AddQueryParam("id", torrentId);
|
||||
|
||||
return url.FullUri;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.HDBits
|
||||
{
|
||||
public class HDBitsRequestGenerator : IIndexerRequestGenerator
|
||||
{
|
||||
public HDBitsSettings Settings { get; set; }
|
||||
|
||||
public virtual IndexerPageableRequestChain GetRecentRequests()
|
||||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
pageableRequests.Add(GetRequest(new TorrentQuery()));
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
public virtual IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
||||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
var query = new TorrentQuery();
|
||||
|
||||
if (TryAddSearchParameters(query, searchCriteria))
|
||||
{
|
||||
pageableRequests.Add(GetRequest(query));
|
||||
}
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
private bool TryAddSearchParameters(TorrentQuery query, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (searchCriteria.ImdbId.IsNullOrWhiteSpace())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var imdbId = int.Parse(searchCriteria.ImdbId.Substring(2));
|
||||
|
||||
if (imdbId != 0)
|
||||
{
|
||||
query.ImdbInfo = query.ImdbInfo ?? new ImdbInfo();
|
||||
query.ImdbInfo.Id = imdbId;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Func<IDictionary<string, string>> GetCookies { get; set; }
|
||||
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||
|
||||
private IEnumerable<IndexerRequest> GetRequest(TorrentQuery query)
|
||||
{
|
||||
var request = new HttpRequestBuilder(Settings.BaseUrl)
|
||||
.Resource("/api/torrents")
|
||||
.Build();
|
||||
|
||||
request.Method = HttpMethod.POST;
|
||||
const string appJson = "application/json";
|
||||
request.Headers.Accept = appJson;
|
||||
request.Headers.ContentType = appJson;
|
||||
|
||||
query.Username = Settings.Username;
|
||||
query.Passkey = Settings.ApiKey;
|
||||
|
||||
query.Category = Settings.Categories.ToArray();
|
||||
query.Codec = Settings.Codecs.ToArray();
|
||||
query.Medium = Settings.Mediums.ToArray();
|
||||
|
||||
request.SetContent(query.ToJson());
|
||||
|
||||
yield return new IndexerRequest(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.HDBits
|
||||
{
|
||||
public class HDBitsSettingsValidator : AbstractValidator<HDBitsSettings>
|
||||
{
|
||||
public HDBitsSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.BaseUrl).ValidRootUrl();
|
||||
RuleFor(c => c.ApiKey).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class HDBitsSettings : ITorrentIndexerSettings
|
||||
{
|
||||
private static readonly HDBitsSettingsValidator Validator = new HDBitsSettingsValidator();
|
||||
|
||||
public HDBitsSettings()
|
||||
{
|
||||
BaseUrl = "https://hdbits.org";
|
||||
MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS;
|
||||
|
||||
Categories = new int[] { (int)HdBitsCategory.Movie };
|
||||
Codecs = System.Array.Empty<int>();
|
||||
Mediums = System.Array.Empty<int>();
|
||||
MultiLanguages = new List<int>();
|
||||
RequiredFlags = new List<int>();
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "Username", Privacy = PrivacyLevel.UserName)]
|
||||
public string Username { get; set; }
|
||||
|
||||
[FieldDefinition(1, Type = FieldType.Select, SelectOptions = typeof(LanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
public IEnumerable<int> MultiLanguages { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "API Key", Privacy = PrivacyLevel.ApiKey)]
|
||||
public string ApiKey { get; set; }
|
||||
|
||||
[FieldDefinition(3, 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(4, Label = "Categories", Type = FieldType.TagSelect, SelectOptions = typeof(HdBitsCategory), Advanced = true, HelpText = "Options: Movie, TV, Documentary, Music, Sport, Audio, XXX, MiscDemo. If unspecified, all options are used.")]
|
||||
public IEnumerable<int> Categories { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Codecs", Type = FieldType.TagSelect, SelectOptions = typeof(HdBitsCodec), Advanced = true, HelpText = "Options: h264, Mpeg2, VC1, Xvid. If unspecified, all options are used.")]
|
||||
public IEnumerable<int> Codecs { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "Mediums", Type = FieldType.TagSelect, SelectOptions = typeof(HdBitsMedium), Advanced = true, HelpText = "Options: BluRay, Encode, Capture, Remux, WebDL. If unspecified, all options are used.")]
|
||||
public IEnumerable<int> Mediums { get; set; }
|
||||
|
||||
[FieldDefinition(7, Type = FieldType.Number, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(8, Type = FieldType.TagSelect, SelectOptions = typeof(IndexerFlags), Label = "Required Flags", HelpText = "What indexer flags are required?", HelpLink = "https://github.com/Prowlarr/Prowlarr/wiki/Indexer-Flags#1-required-flags", Advanced = true)]
|
||||
public IEnumerable<int> RequiredFlags { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
}
|
||||
|
||||
public enum HdBitsCategory
|
||||
{
|
||||
Movie = 1,
|
||||
Tv = 2,
|
||||
Documentary = 3,
|
||||
Music = 4,
|
||||
Sport = 5,
|
||||
Audio = 6,
|
||||
Xxx = 7,
|
||||
MiscDemo = 8
|
||||
}
|
||||
|
||||
public enum HdBitsCodec
|
||||
{
|
||||
H264 = 1,
|
||||
Mpeg2 = 2,
|
||||
Vc1 = 3,
|
||||
Xvid = 4,
|
||||
HEVC = 5
|
||||
}
|
||||
|
||||
public enum HdBitsMedium
|
||||
{
|
||||
Bluray = 1,
|
||||
Encode = 3,
|
||||
Capture = 4,
|
||||
Remux = 5,
|
||||
WebDl = 6
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user