mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-04-24 13:57:11 -04:00
Fixed: (GGn) Improve title, timezone, MST, min/max size filters
Hiding torrents of type link And some minor refactoring around the passkey fetching and parsing.
This commit is contained in:
parent
bf47380f7b
commit
f9c9d4a0e0
2 changed files with 205 additions and 112 deletions
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
@ -21,10 +22,10 @@ namespace NzbDrone.Core.Test.IndexerTests.GazelleGamesTests
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
Subject.Definition = new IndexerDefinition()
|
Subject.Definition = new IndexerDefinition
|
||||||
{
|
{
|
||||||
Name = "GazelleGames",
|
Name = "GazelleGames",
|
||||||
Settings = new GazelleGamesSettings() { Apikey = "somekey" }
|
Settings = new GazelleGamesSettings { Apikey = "somekey" }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,20 +38,20 @@ namespace NzbDrone.Core.Test.IndexerTests.GazelleGamesTests
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader { { "Content-Type", "application/json" } }, new CookieCollection(), recentFeed)));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader { { "Content-Type", "application/json" } }, new CookieCollection(), recentFeed)));
|
||||||
|
|
||||||
var releases = (await Subject.Fetch(new BasicSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
var releases = (await Subject.Fetch(new BasicSearchCriteria { Categories = new[] { 2000 } })).Releases;
|
||||||
|
|
||||||
releases.Should().HaveCount(1464);
|
releases.Should().HaveCount(1463);
|
||||||
releases.First().Should().BeOfType<TorrentInfo>();
|
releases.First().Should().BeOfType<TorrentInfo>();
|
||||||
|
|
||||||
var torrentInfo = releases.First() as TorrentInfo;
|
var torrentInfo = releases.First() as TorrentInfo;
|
||||||
|
|
||||||
torrentInfo.Title.Should().Be("Microsoft_Flight_Simulator-HOODLUM");
|
torrentInfo.Title.Should().Be("Microsoft_Flight_Simulator-HOODLUM (2020) [Windows / Multi-Language / Full ISO]");
|
||||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||||
torrentInfo.DownloadUrl.Should().Be("https://gazellegames.net/torrents.php?action=download&id=303216&authkey=prowlarr&torrent_pass=");
|
torrentInfo.DownloadUrl.Should().Be("https://gazellegames.net/torrents.php?action=download&id=303216&authkey=prowlarr&torrent_pass=");
|
||||||
torrentInfo.InfoUrl.Should().Be("https://gazellegames.net/torrents.php?id=84781&torrentid=303216");
|
torrentInfo.InfoUrl.Should().Be("https://gazellegames.net/torrents.php?id=84781&torrentid=303216");
|
||||||
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
||||||
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
||||||
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2022-07-25 6:39:11").ToUniversalTime());
|
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2022-07-25 06:39:11", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal));
|
||||||
torrentInfo.Size.Should().Be(80077617780);
|
torrentInfo.Size.Should().Be(80077617780);
|
||||||
torrentInfo.InfoHash.Should().Be(null);
|
torrentInfo.InfoHash.Should().Be(null);
|
||||||
torrentInfo.MagnetUrl.Should().Be(null);
|
torrentInfo.MagnetUrl.Should().Be(null);
|
||||||
|
@ -74,7 +75,7 @@ namespace NzbDrone.Core.Test.IndexerTests.GazelleGamesTests
|
||||||
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
.Setup(o => o.ExecuteProxiedAsync(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get), Subject.Definition))
|
||||||
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader { { "Content-Type", "application/json" } }, new CookieCollection(), recentFeed)));
|
.Returns<HttpRequest, IndexerDefinition>((r, d) => Task.FromResult(new HttpResponse(r, new HttpHeader { { "Content-Type", "application/json" } }, new CookieCollection(), recentFeed)));
|
||||||
|
|
||||||
var releases = (await Subject.Fetch(new BasicSearchCriteria { Categories = new int[] { 2000 } })).Releases;
|
var releases = (await Subject.Fetch(new BasicSearchCriteria { Categories = new[] { 2000 } })).Releases;
|
||||||
|
|
||||||
releases.Should().HaveCount(0);
|
releases.Should().HaveCount(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
|
@ -16,6 +19,7 @@ using NzbDrone.Core.Indexers.Exceptions;
|
||||||
using NzbDrone.Core.Indexers.Settings;
|
using NzbDrone.Core.Indexers.Settings;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
|
@ -24,7 +28,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
public class GazelleGames : TorrentIndexerBase<GazelleGamesSettings>
|
public class GazelleGames : TorrentIndexerBase<GazelleGamesSettings>
|
||||||
{
|
{
|
||||||
public override string Name => "GazelleGames";
|
public override string Name => "GazelleGames";
|
||||||
public override string[] IndexerUrls => new string[] { "https://gazellegames.net/" };
|
public override string[] IndexerUrls => new[] { "https://gazellegames.net/" };
|
||||||
public override string Description => "GazelleGames (GGn) is a Private Torrent Tracker for GAMES";
|
public override string Description => "GazelleGames (GGn) is a Private Torrent Tracker for GAMES";
|
||||||
public override string Language => "en-US";
|
public override string Language => "en-US";
|
||||||
public override Encoding Encoding => Encoding.UTF8;
|
public override Encoding Encoding => Encoding.UTF8;
|
||||||
|
@ -38,7 +42,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
|
|
||||||
public override IIndexerRequestGenerator GetRequestGenerator()
|
public override IIndexerRequestGenerator GetRequestGenerator()
|
||||||
{
|
{
|
||||||
return new GazelleGamesRequestGenerator() { Settings = Settings, Capabilities = Capabilities, HttpClient = _httpClient };
|
return new GazelleGamesRequestGenerator(Settings, Capabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IParseIndexerResponse GetParser()
|
public override IParseIndexerResponse GetParser()
|
||||||
|
@ -48,14 +52,13 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
|
|
||||||
private IndexerCapabilities SetCapabilities()
|
private IndexerCapabilities SetCapabilities()
|
||||||
{
|
{
|
||||||
var caps = new IndexerCapabilities
|
var caps = new IndexerCapabilities();
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
// Apple
|
// Apple
|
||||||
caps.Categories.AddCategoryMapping("Mac", NewznabStandardCategory.ConsoleOther, "Mac");
|
caps.Categories.AddCategoryMapping("Mac", NewznabStandardCategory.ConsoleOther, "Mac");
|
||||||
caps.Categories.AddCategoryMapping("iOS", NewznabStandardCategory.PCMobileiOS, "iOS");
|
caps.Categories.AddCategoryMapping("iOS", NewznabStandardCategory.PCMobileiOS, "iOS");
|
||||||
caps.Categories.AddCategoryMapping("Apple Bandai Pippin", NewznabStandardCategory.ConsoleOther, "Apple Bandai Pippin");
|
caps.Categories.AddCategoryMapping("Apple Bandai Pippin", NewznabStandardCategory.ConsoleOther, "Apple Bandai Pippin");
|
||||||
|
caps.Categories.AddCategoryMapping("Apple II", NewznabStandardCategory.ConsoleOther, "Apple II");
|
||||||
|
|
||||||
// Google
|
// Google
|
||||||
caps.Categories.AddCategoryMapping("Android", NewznabStandardCategory.PCMobileAndroid, "Android");
|
caps.Categories.AddCategoryMapping("Android", NewznabStandardCategory.PCMobileAndroid, "Android");
|
||||||
|
@ -78,6 +81,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
caps.Categories.AddCategoryMapping("Nintendo GameCube", NewznabStandardCategory.ConsoleOther, "Nintendo GameCube");
|
caps.Categories.AddCategoryMapping("Nintendo GameCube", NewznabStandardCategory.ConsoleOther, "Nintendo GameCube");
|
||||||
caps.Categories.AddCategoryMapping("Pokemon Mini", NewznabStandardCategory.ConsoleOther, "Pokemon Mini");
|
caps.Categories.AddCategoryMapping("Pokemon Mini", NewznabStandardCategory.ConsoleOther, "Pokemon Mini");
|
||||||
caps.Categories.AddCategoryMapping("SNES", NewznabStandardCategory.ConsoleOther, "SNES");
|
caps.Categories.AddCategoryMapping("SNES", NewznabStandardCategory.ConsoleOther, "SNES");
|
||||||
|
caps.Categories.AddCategoryMapping("Switch", NewznabStandardCategory.ConsoleOther, "Switch");
|
||||||
caps.Categories.AddCategoryMapping("Virtual Boy", NewznabStandardCategory.ConsoleOther, "Virtual Boy");
|
caps.Categories.AddCategoryMapping("Virtual Boy", NewznabStandardCategory.ConsoleOther, "Virtual Boy");
|
||||||
caps.Categories.AddCategoryMapping("Wii", NewznabStandardCategory.ConsoleWii, "Wii");
|
caps.Categories.AddCategoryMapping("Wii", NewznabStandardCategory.ConsoleWii, "Wii");
|
||||||
caps.Categories.AddCategoryMapping("Wii U", NewznabStandardCategory.ConsoleWiiU, "Wii U");
|
caps.Categories.AddCategoryMapping("Wii U", NewznabStandardCategory.ConsoleWiiU, "Wii U");
|
||||||
|
@ -178,31 +182,62 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
caps.Categories.AddCategoryMapping("Retro - Other", NewznabStandardCategory.ConsoleOther, "Retro - Other");
|
caps.Categories.AddCategoryMapping("Retro - Other", NewznabStandardCategory.ConsoleOther, "Retro - Other");
|
||||||
|
|
||||||
// special categories (real categories/not platforms)
|
// special categories (real categories/not platforms)
|
||||||
caps.Categories.AddCategoryMapping("OST", NewznabStandardCategory.AudioOther, "OST");
|
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.PCGames, "Games");
|
||||||
caps.Categories.AddCategoryMapping("Applications", NewznabStandardCategory.PC0day, "Applications");
|
caps.Categories.AddCategoryMapping(2, NewznabStandardCategory.PC0day, "Applications");
|
||||||
caps.Categories.AddCategoryMapping("E-Books", NewznabStandardCategory.BooksEBook, "E-Books");
|
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.BooksEBook, "E-Books");
|
||||||
|
caps.Categories.AddCategoryMapping(4, NewznabStandardCategory.AudioOther, "OST");
|
||||||
|
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task Test(List<ValidationFailure> failures)
|
protected override async Task Test(List<ValidationFailure> failures)
|
||||||
{
|
{
|
||||||
((GazelleGamesRequestGenerator)GetRequestGenerator()).FetchPasskey();
|
await FetchPasskey().ConfigureAwait(false);
|
||||||
await base.Test(failures);
|
|
||||||
|
await base.Test(failures).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task FetchPasskey()
|
||||||
|
{
|
||||||
|
var request = new HttpRequestBuilder($"{Settings.BaseUrl.Trim().TrimEnd('/')}/api.php")
|
||||||
|
.Accept(HttpAccept.Json)
|
||||||
|
.SetHeader("X-API-Key", Settings.Apikey)
|
||||||
|
.AddQueryParam("request", "quick_user")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var indexResponse = await _httpClient.ExecuteAsync(request).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var index = Json.Deserialize<GazelleGamesUserResponse>(indexResponse.Content);
|
||||||
|
|
||||||
|
if (index == null ||
|
||||||
|
string.IsNullOrWhiteSpace(index.Status) ||
|
||||||
|
index.Status != "success" ||
|
||||||
|
string.IsNullOrWhiteSpace(index.Response.PassKey))
|
||||||
|
{
|
||||||
|
throw new IndexerAuthException("Failed to authenticate with GazelleGames.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set passkey on settings so it can be used to generate the download URL
|
||||||
|
Settings.Passkey = index.Response.PassKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GazelleGamesRequestGenerator : IIndexerRequestGenerator
|
public class GazelleGamesRequestGenerator : IIndexerRequestGenerator
|
||||||
{
|
{
|
||||||
public GazelleGamesSettings Settings { get; set; }
|
private readonly GazelleGamesSettings _settings;
|
||||||
public IndexerCapabilities Capabilities { get; set; }
|
private readonly IndexerCapabilities _capabilities;
|
||||||
public IIndexerHttpClient HttpClient { get; set; }
|
|
||||||
|
public GazelleGamesRequestGenerator(GazelleGamesSettings settings, IndexerCapabilities capabilities)
|
||||||
|
{
|
||||||
|
_settings = settings;
|
||||||
|
_capabilities = capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
||||||
{
|
{
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
var pageableRequests = new IndexerPageableRequestChain();
|
||||||
|
|
||||||
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories)));
|
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria)));
|
||||||
|
|
||||||
return pageableRequests;
|
return pageableRequests;
|
||||||
}
|
}
|
||||||
|
@ -211,7 +246,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
{
|
{
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
var pageableRequests = new IndexerPageableRequestChain();
|
||||||
|
|
||||||
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories)));
|
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria)));
|
||||||
|
|
||||||
return pageableRequests;
|
return pageableRequests;
|
||||||
}
|
}
|
||||||
|
@ -220,7 +255,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
{
|
{
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
var pageableRequests = new IndexerPageableRequestChain();
|
||||||
|
|
||||||
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories)));
|
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria)));
|
||||||
|
|
||||||
return pageableRequests;
|
return pageableRequests;
|
||||||
}
|
}
|
||||||
|
@ -229,7 +264,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
{
|
{
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
var pageableRequests = new IndexerPageableRequestChain();
|
||||||
|
|
||||||
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories)));
|
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria)));
|
||||||
|
|
||||||
return pageableRequests;
|
return pageableRequests;
|
||||||
}
|
}
|
||||||
|
@ -238,61 +273,72 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
{
|
{
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
var pageableRequests = new IndexerPageableRequestChain();
|
||||||
|
|
||||||
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria.Categories)));
|
pageableRequests.Add(GetRequest(GetBasicSearchParameters(searchCriteria.SanitizedSearchTerm, searchCriteria)));
|
||||||
|
|
||||||
return pageableRequests;
|
return pageableRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FetchPasskey()
|
private IEnumerable<IndexerRequest> GetRequest(List<KeyValuePair<string, string>> parameters)
|
||||||
{
|
{
|
||||||
// GET on index for the passkey
|
var request = RequestBuilder()
|
||||||
var request = RequestBuilder().Resource("api.php?request=quick_user").Build();
|
.Resource($"/api.php?{parameters.GetQueryString()}")
|
||||||
var indexResponse = HttpClient.Execute(request);
|
|
||||||
var index = Json.Deserialize<GazelleGamesUserResponse>(indexResponse.Content);
|
|
||||||
if (index == null ||
|
|
||||||
string.IsNullOrWhiteSpace(index.Status) ||
|
|
||||||
index.Status != "success" ||
|
|
||||||
string.IsNullOrWhiteSpace(index.Response.PassKey))
|
|
||||||
{
|
|
||||||
throw new Exception("Failed to authenticate with GazelleGames.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set passkey on settings so it can be used to generate the download URL
|
|
||||||
Settings.Passkey = index.Response.PassKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<IndexerRequest> GetRequest(string parameters)
|
|
||||||
{
|
|
||||||
var req = RequestBuilder()
|
|
||||||
.Resource($"api.php?{parameters}")
|
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
yield return new IndexerRequest(req);
|
yield return new IndexerRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpRequestBuilder RequestBuilder()
|
private HttpRequestBuilder RequestBuilder()
|
||||||
{
|
{
|
||||||
return new HttpRequestBuilder($"{Settings.BaseUrl.Trim().TrimEnd('/')}")
|
return new HttpRequestBuilder($"{_settings.BaseUrl.Trim().TrimEnd('/')}")
|
||||||
|
.Resource("/api.php")
|
||||||
.Accept(HttpAccept.Json)
|
.Accept(HttpAccept.Json)
|
||||||
.SetHeader("X-API-Key", Settings.Apikey);
|
.SetHeader("X-API-Key", _settings.Apikey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetBasicSearchParameters(string searchTerm, int[] categories)
|
private List<KeyValuePair<string, string>> GetBasicSearchParameters(string searchTerm, SearchCriteriaBase searchCriteria)
|
||||||
{
|
{
|
||||||
var parameters = "request=search&search_type=torrents&empty_groups=filled&order_by=time&order_way=desc";
|
var parameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(searchTerm))
|
|
||||||
{
|
{
|
||||||
var searchType = Settings.SearchGroupNames ? "groupname" : "searchstr";
|
{ "request", "search" },
|
||||||
|
{ "search_type", "torrents" },
|
||||||
|
{ "empty_groups", "filled" },
|
||||||
|
{ "order_by", "time" },
|
||||||
|
{ "order_way", "desc" }
|
||||||
|
};
|
||||||
|
|
||||||
parameters += string.Format("&{1}={0}", searchTerm.Replace(".", " "), searchType);
|
if (searchTerm.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
parameters.Add(
|
||||||
|
_settings.SearchGroupNames ? "groupname" : "searchstr",
|
||||||
|
searchTerm.Replace(".", " "));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (categories != null)
|
if (searchCriteria.Categories != null)
|
||||||
{
|
{
|
||||||
foreach (var cat in Capabilities.Categories.MapTorznabCapsToTrackers(categories))
|
var categoryMappings = _capabilities.Categories
|
||||||
|
.MapTorznabCapsToTrackers(searchCriteria.Categories)
|
||||||
|
.Distinct()
|
||||||
|
.Where(x => !x.IsAllDigits())
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
categoryMappings.ForEach(category => parameters.Add("artistcheck[]", category));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchCriteria.MinSize is > 0)
|
||||||
|
{
|
||||||
|
var minSize = searchCriteria.MinSize.Value / 1024L / 1024L;
|
||||||
|
if (minSize > 0)
|
||||||
{
|
{
|
||||||
parameters += string.Format("&artistcheck[]={0}", cat);
|
parameters.Add("sizesmall", minSize.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchCriteria.MaxSize is > 0)
|
||||||
|
{
|
||||||
|
var maxSize = searchCriteria.MaxSize.Value / 1024L / 1024L;
|
||||||
|
if (maxSize > 0)
|
||||||
|
{
|
||||||
|
parameters.Add("sizeslarge", maxSize.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,66 +375,63 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
}
|
}
|
||||||
|
|
||||||
var jsonResponse = new HttpResponse<GazelleGamesResponse>(indexerResponse.HttpResponse);
|
var jsonResponse = new HttpResponse<GazelleGamesResponse>(indexerResponse.HttpResponse);
|
||||||
|
|
||||||
if (jsonResponse.Resource.Status != "success" ||
|
if (jsonResponse.Resource.Status != "success" ||
|
||||||
string.IsNullOrWhiteSpace(jsonResponse.Resource.Status) ||
|
string.IsNullOrWhiteSpace(jsonResponse.Resource.Status) ||
|
||||||
jsonResponse.Resource.Response == null)
|
jsonResponse.Resource.Response is not JObject response)
|
||||||
{
|
{
|
||||||
return torrentInfos;
|
return torrentInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary<string, GazelleGamesGroup> response;
|
var groups = response.ToObject<Dictionary<int, GazelleGamesGroup>>(JsonSerializer.Create(Json.GetSerializerSettings()));
|
||||||
|
|
||||||
try
|
foreach (var group in groups)
|
||||||
{
|
{
|
||||||
response = ((JObject)jsonResponse.Resource.Response).ToObject<Dictionary<string, GazelleGamesGroup>>();
|
if (group.Value.Torrents is not JObject groupTorrents)
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return torrentInfos;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var result in response)
|
|
||||||
{
|
|
||||||
Dictionary<string, GazelleGamesTorrent> torrents;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
torrents = ((JObject)result.Value.Torrents).ToObject<Dictionary<string, GazelleGamesTorrent>>();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.Value.Torrents != null)
|
var torrents = groupTorrents
|
||||||
|
.ToObject<Dictionary<int, GazelleGamesTorrent>>(JsonSerializer.Create(Json.GetSerializerSettings()))
|
||||||
|
.Where(t => t.Value.TorrentType != "Link")
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var categories = group.Value.Artists
|
||||||
|
.SelectMany(a => _categories.MapTrackerCatDescToNewznab(a.Name))
|
||||||
|
.Distinct()
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
foreach (var torrent in torrents)
|
||||||
{
|
{
|
||||||
var categories = result.Value.Artists.Select(a => a.Name);
|
var torrentId = torrent.Key;
|
||||||
|
var infoUrl = GetInfoUrl(group.Key, torrentId);
|
||||||
|
|
||||||
foreach (var torrent in torrents)
|
if (categories.Length == 0)
|
||||||
{
|
{
|
||||||
var id = int.Parse(torrent.Key);
|
categories = _categories.MapTrackerCatToNewznab(torrent.Value.CategoryId.ToString()).ToArray();
|
||||||
|
|
||||||
var infoUrl = GetInfoUrl(result.Key, id);
|
|
||||||
|
|
||||||
var release = new TorrentInfo()
|
|
||||||
{
|
|
||||||
Guid = infoUrl,
|
|
||||||
Title = torrent.Value.ReleaseTitle,
|
|
||||||
Files = torrent.Value.FileCount,
|
|
||||||
Grabs = torrent.Value.Snatched,
|
|
||||||
Size = long.Parse(torrent.Value.Size),
|
|
||||||
DownloadUrl = GetDownloadUrl(id),
|
|
||||||
InfoUrl = infoUrl,
|
|
||||||
Seeders = torrent.Value.Seeders,
|
|
||||||
Categories = _categories.MapTrackerCatDescToNewznab(categories.FirstOrDefault()),
|
|
||||||
Peers = torrent.Value.Leechers + torrent.Value.Seeders,
|
|
||||||
PublishDate = torrent.Value.Time.ToUniversalTime(),
|
|
||||||
DownloadVolumeFactor = torrent.Value.FreeTorrent == GazelleGamesFreeTorrent.FreeLeech || torrent.Value.FreeTorrent == GazelleGamesFreeTorrent.Neutral || torrent.Value.LowSeedFL ? 0 : 1,
|
|
||||||
UploadVolumeFactor = torrent.Value.FreeTorrent == GazelleGamesFreeTorrent.Neutral ? 0 : 1
|
|
||||||
};
|
|
||||||
|
|
||||||
torrentInfos.Add(release);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var release = new TorrentInfo
|
||||||
|
{
|
||||||
|
Guid = infoUrl,
|
||||||
|
InfoUrl = infoUrl,
|
||||||
|
DownloadUrl = GetDownloadUrl(torrentId),
|
||||||
|
Title = GetTitle(group.Value, torrent.Value),
|
||||||
|
Categories = categories,
|
||||||
|
Files = torrent.Value.FileCount,
|
||||||
|
Size = long.Parse(torrent.Value.Size),
|
||||||
|
Grabs = torrent.Value.Snatched,
|
||||||
|
Seeders = torrent.Value.Seeders,
|
||||||
|
Peers = torrent.Value.Leechers + torrent.Value.Seeders,
|
||||||
|
PublishDate = torrent.Value.Time.ToUniversalTime(),
|
||||||
|
Scene = torrent.Value.Scene == 1,
|
||||||
|
DownloadVolumeFactor = torrent.Value.FreeTorrent is GazelleGamesFreeTorrent.FreeLeech or GazelleGamesFreeTorrent.Neutral || torrent.Value.LowSeedFL ? 0 : 1,
|
||||||
|
UploadVolumeFactor = torrent.Value.FreeTorrent == GazelleGamesFreeTorrent.Neutral ? 0 : 1,
|
||||||
|
MinimumSeedTime = 288000 // Minimum of 3 days and 8 hours (80 hours in total)
|
||||||
|
};
|
||||||
|
|
||||||
|
torrentInfos.Add(release);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,6 +442,44 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetTitle(GazelleGamesGroup group, GazelleGamesTorrent torrent)
|
||||||
|
{
|
||||||
|
var title = WebUtility.HtmlDecode(torrent.ReleaseTitle);
|
||||||
|
|
||||||
|
if (group.Year is > 0 && !title.Contains(group.Year.ToString()))
|
||||||
|
{
|
||||||
|
title += $" ({group.Year})";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (torrent.RemasterTitle.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
title += $" [{$"{torrent.RemasterTitle} {torrent.RemasterYear}".Trim()}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
var flags = new List<string>
|
||||||
|
{
|
||||||
|
$"{torrent.Format} {torrent.Encoding}".Trim()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (group.Artists is { Count: > 0 })
|
||||||
|
{
|
||||||
|
flags.AddIfNotNull(group.Artists.Select(a => a.Name).Join(", "));
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.AddIfNotNull(torrent.Language);
|
||||||
|
flags.AddIfNotNull(torrent.Region);
|
||||||
|
flags.AddIfNotNull(torrent.Miscellaneous);
|
||||||
|
|
||||||
|
flags = flags.Where(x => x.IsNotNullOrWhiteSpace()).ToList();
|
||||||
|
|
||||||
|
if (flags.Any())
|
||||||
|
{
|
||||||
|
title += $" [{string.Join(" / ", flags)}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
private string GetDownloadUrl(int torrentId)
|
private string GetDownloadUrl(int torrentId)
|
||||||
{
|
{
|
||||||
// AuthKey is required but not checked, just pass in a dummy variable
|
// AuthKey is required but not checked, just pass in a dummy variable
|
||||||
|
@ -413,7 +494,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
return url.FullUri;
|
return url.FullUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetInfoUrl(string groupId, int torrentId)
|
private string GetInfoUrl(int groupId, int torrentId)
|
||||||
{
|
{
|
||||||
var url = new HttpUri(_settings.BaseUrl)
|
var url = new HttpUri(_settings.BaseUrl)
|
||||||
.CombinePath("/torrents.php")
|
.CombinePath("/torrents.php")
|
||||||
|
@ -444,7 +525,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
Passkey = "";
|
Passkey = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
[FieldDefinition(2, Label = "API Key", HelpText = "API Key from the Site (Found in Settings => Access Settings), Must have User Permissions", Privacy = PrivacyLevel.ApiKey)]
|
[FieldDefinition(2, Label = "API Key", HelpText = "API Key from the Site (Found in Settings => Access Settings)", HelpTextWarning = "Must have User and Torrents permissions", Privacy = PrivacyLevel.ApiKey)]
|
||||||
public string Apikey { get; set; }
|
public string Apikey { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(3, Label = "Search Group Names", Type = FieldType.Checkbox, HelpText = "Search Group Names Only")]
|
[FieldDefinition(3, Label = "Search Group Names", Type = FieldType.Checkbox, HelpText = "Search Group Names Only")]
|
||||||
|
@ -466,8 +547,9 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
|
|
||||||
public class GazelleGamesGroup
|
public class GazelleGamesGroup
|
||||||
{
|
{
|
||||||
public List<GazelleGamesArtist> Artists { get; set; }
|
public ReadOnlyCollection<GazelleGamesArtist> Artists { get; set; }
|
||||||
public object Torrents { get; set; }
|
public object Torrents { get; set; }
|
||||||
|
public int? Year { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GazelleGamesArtist
|
public class GazelleGamesArtist
|
||||||
|
@ -478,13 +560,23 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
|
|
||||||
public class GazelleGamesTorrent
|
public class GazelleGamesTorrent
|
||||||
{
|
{
|
||||||
|
public int CategoryId { get; set; }
|
||||||
|
public string Format { get; set; }
|
||||||
|
public string Encoding { get; set; }
|
||||||
|
public string Language { get; set; }
|
||||||
|
public string Region { get; set; }
|
||||||
|
public string RemasterYear { get; set; }
|
||||||
|
public string RemasterTitle { get; set; }
|
||||||
|
public string ReleaseTitle { get; set; }
|
||||||
|
public string Miscellaneous { get; set; }
|
||||||
|
public int Scene { get; set; }
|
||||||
|
public DateTime Time { get; set; }
|
||||||
|
public string TorrentType { get; set; }
|
||||||
|
public int FileCount { get; set; }
|
||||||
public string Size { get; set; }
|
public string Size { get; set; }
|
||||||
public int? Snatched { get; set; }
|
public int? Snatched { get; set; }
|
||||||
public int Seeders { get; set; }
|
public int Seeders { get; set; }
|
||||||
public int Leechers { get; set; }
|
public int Leechers { get; set; }
|
||||||
public string ReleaseTitle { get; set; }
|
|
||||||
public DateTime Time { get; set; }
|
|
||||||
public int FileCount { get; set; }
|
|
||||||
public GazelleGamesFreeTorrent FreeTorrent { get; set; }
|
public GazelleGamesFreeTorrent FreeTorrent { get; set; }
|
||||||
public bool PersonalFL { get; set; }
|
public bool PersonalFL { get; set; }
|
||||||
public bool LowSeedFL { get; set; }
|
public bool LowSeedFL { get; set; }
|
||||||
|
@ -503,9 +595,9 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||||
|
|
||||||
public enum GazelleGamesFreeTorrent
|
public enum GazelleGamesFreeTorrent
|
||||||
{
|
{
|
||||||
Normal,
|
Normal = 0,
|
||||||
FreeLeech,
|
FreeLeech = 1,
|
||||||
Neutral,
|
Neutral = 2,
|
||||||
Either
|
Either = 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue