Files
Prowlarr/src/NzbDrone.Core/Indexers/Definitions/HDBits/HDBitsParser.cs
T
Bogdan 2d584f7eb6 New: Support for exclusive indexer flag
Co-authored-by: zakkarry <zak@ary.dev>
2025-02-18 02:11:57 +02:00

167 lines
5.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Indexers.Definitions.HDBits
{
public class HDBitsParser : IParseIndexerResponse
{
private readonly HDBitsSettings _settings;
private readonly IndexerCapabilitiesCategories _categories;
private readonly List<int> _halfLeechMediums = new () { (int)HdBitsMedium.Bluray, (int)HdBitsMedium.Remux, (int)HdBitsMedium.Capture };
public HDBitsParser(HDBitsSettings settings, IndexerCapabilitiesCategories categories)
{
_settings = settings;
_categories = categories;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var indexerHttpResponse = indexerResponse.HttpResponse;
if (indexerHttpResponse.StatusCode == HttpStatusCode.Forbidden)
{
throw new RequestLimitReachedException(indexerResponse, "HDBits Query Limit Reached. Please try again later.");
}
if (indexerHttpResponse.StatusCode != HttpStatusCode.OK)
{
throw new IndexerException(indexerResponse, "Unexpected response status {0} code from indexer request", indexerHttpResponse.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);
}
if (jsonResponse.Data is not JArray responseData)
{
throw new IndexerException(indexerResponse, "Indexer API call response missing result data");
}
var releaseInfos = new List<ReleaseInfo>();
var queryResults = responseData.ToObject<TorrentQueryResponse[]>();
foreach (var result in queryResults)
{
// Skip non-freeleech results when freeleech only is set
if (_settings.FreeleechOnly && result.FreeLeech != "yes")
{
continue;
}
var id = result.Id;
releaseInfos.Add(new TorrentInfo
{
Guid = $"HDBits-{id}",
Title = GetTitle(result),
Size = result.Size,
Categories = _categories.MapTrackerCatToNewznab(result.TypeCategory.ToString()),
InfoHash = result.Hash,
DownloadUrl = GetDownloadUrl(id),
InfoUrl = GetInfoUrl(id),
Seeders = result.Seeders,
Grabs = (int)result.TimesCompleted,
Files = (int)result.NumFiles,
Peers = result.Leechers + result.Seeders,
PublishDate = result.Added.ToUniversalTime(),
Year = result.ImdbInfo?.Year ?? 0,
ImdbId = result.ImdbInfo?.Id ?? 0,
TvdbId = result.TvdbInfo?.Id ?? 0,
DownloadVolumeFactor = GetDownloadVolumeFactor(result),
UploadVolumeFactor = GetUploadVolumeFactor(result),
IndexerFlags = GetIndexerFlags(result)
});
}
return releaseInfos.ToArray();
}
private string GetTitle(TorrentQueryResponse item)
{
// Use release name for XXX content and full discs
return item.TypeCategory != 7 && item.TypeMedium != 1 && _settings.UseFilenames && item.FileName.IsNotNullOrWhiteSpace()
? item.FileName.Replace(".torrent", "", StringComparison.InvariantCultureIgnoreCase)
: item.Name;
}
private static HashSet<IndexerFlag> GetIndexerFlags(TorrentQueryResponse item)
{
var flags = new HashSet<IndexerFlag>();
if (item.TypeOrigin == 1)
{
flags.Add(IndexerFlag.Internal);
}
if (item.TypeExclusive == 1)
{
flags.Add(IndexerFlag.Exclusive);
}
return flags;
}
private double GetDownloadVolumeFactor(TorrentQueryResponse item)
{
if (item.FreeLeech == "yes")
{
return 0;
}
// 100% Neutral Leech: all XXX content.
if (item.TypeCategory == 7)
{
return 0;
}
// 50% Free Leech: all full discs, remuxes, captures and all internal encodes, also all TV and Documentary content.
if (_halfLeechMediums.Contains(item.TypeMedium) || item.TypeOrigin == 1 || item.TypeCategory is 2 or 3)
{
return 0.5;
}
return 1;
}
private static double GetUploadVolumeFactor(TorrentQueryResponse item)
{
// 100% Neutral Leech: all XXX content.
return item.TypeCategory == 7 ? 0 : 1;
}
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;
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
}