Fixup Gazelle Parsing, Rework Auth to allow Indexer Override

pull/7/head
Qstick 3 years ago
parent 69a55ea858
commit da60543c72

@ -1,3 +1,4 @@
using System;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
@ -8,6 +9,7 @@ namespace NzbDrone.Core.Indexers.Gazelle
{
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override string BaseUrl => "";
protected virtual string LoginUrl => BaseUrl + "login.php";
public override bool SupportsRss => true;
public override bool SupportsSearch => true;
public override int PageSize => 50;
@ -44,5 +46,50 @@ namespace NzbDrone.Core.Indexers.Gazelle
return caps;
}
protected override void DoLogin()
{
var requestBuilder = new HttpRequestBuilder(LoginUrl)
{
LogResponseContent = true
};
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var cookies = Cookies;
Cookies = null;
var authLoginRequest = requestBuilder
.AddFormParameter("username", Settings.Username)
.AddFormParameter("password", Settings.Password)
.AddFormParameter("keeplogged", "1")
.SetHeader("Content-Type", "multipart/form-data")
.Accept(HttpAccept.Json)
.Build();
var response = _httpClient.Execute(authLoginRequest);
cookies = response.GetCookies();
Cookies = cookies;
UpdateCookies(cookies, DateTime.Now + TimeSpan.FromDays(30));
_logger.Debug("Gazelle authentication succeeded.");
//Settings.AuthKey = index.Response.Authkey;
//Settings.PassKey = index.Response.Passkey;
}
protected override bool CheckIfLoginNeeded(HttpResponse response)
{
if (response.HasHttpRedirect || (response.Content != null && response.Content.Contains("\"bad credentials\"")))
{
return true;
}
return false;
}
}
}

@ -43,6 +43,13 @@ namespace NzbDrone.Core.Indexers.Gazelle
{
public string GroupId { get; set; }
public string GroupName { get; set; }
public int TorrentId { get; set; }
public string Size { get; set; }
public int FileCount { get; set; }
public string Snatches { get; set; }
public string Seeders { get; set; }
public string Leechers { get; set; }
public string Category { get; set; }
public string Artist { get; set; }
public string GroupYear { get; set; }
public string Cover { get; set; }
@ -52,8 +59,12 @@ namespace NzbDrone.Core.Indexers.Gazelle
public int TotalSeeders { get; set; }
public int TotalSnatched { get; set; }
public long MaxSize { get; set; }
public string GroupTime { get; set; }
public long GroupTime { get; set; }
public List<GazelleTorrent> Torrents { get; set; }
public bool IsFreeLeech { get; set; }
public bool IsNeutralLeech { get; set; }
public bool IsPersonalFreeLeech { get; set; }
public bool CanUseToken { get; set; }
}
public class GazelleResponse

@ -73,6 +73,7 @@ namespace NzbDrone.Core.Indexers.Gazelle
Guid = string.Format("Gazelle-{0}", id),
Title = WebUtility.HtmlDecode(title),
Container = torrent.Encoding,
Files = torrent.FileCount,
Codec = torrent.Format,
Size = long.Parse(torrent.Size),
DownloadUrl = GetDownloadUrl(id),
@ -96,6 +97,36 @@ namespace NzbDrone.Core.Indexers.Gazelle
torrentInfos.Add(release);
}
}
else
{
var id = result.TorrentId;
var groupName = WebUtility.HtmlDecode(result.GroupName);
var release = new GazelleInfo()
{
Guid = string.Format("Gazelle-{0}", id),
Title = groupName,
Size = long.Parse(result.Size),
DownloadUrl = GetDownloadUrl(id),
InfoUrl = GetInfoUrl(result.GroupId, id),
Seeders = int.Parse(result.Seeders),
Peers = int.Parse(result.Leechers) + int.Parse(result.Seeders),
Files = result.FileCount,
PublishDate = DateTimeOffset.FromUnixTimeSeconds(result.GroupTime).UtcDateTime,
};
var category = result.Category;
if (category == null || category.Contains("Select Category"))
{
release.Category = _capabilities.Categories.MapTrackerCatToNewznab("1");
}
else
{
release.Category = _capabilities.Categories.MapTrackerCatDescToNewznab(category);
}
torrentInfos.Add(release);
}
}
// order by date
@ -110,9 +141,7 @@ namespace NzbDrone.Core.Indexers.Gazelle
var url = new HttpUri(_baseUrl)
.CombinePath("/torrents.php")
.AddQueryParam("action", "download")
.AddQueryParam("id", torrentId)
.AddQueryParam("authkey", _settings.AuthKey)
.AddQueryParam("torrent_pass", _settings.PassKey);
.AddQueryParam("id", torrentId);
return url.FullUri;
}

@ -20,7 +20,6 @@ namespace NzbDrone.Core.Indexers.Gazelle
public IndexerCapabilities Capabilities { get; set; }
public Logger Logger { get; set; }
protected virtual string LoginUrl => BaseUrl + "login.php";
protected virtual string APIUrl => BaseUrl + "ajax.php";
protected virtual string DownloadUrl => BaseUrl + "torrents.php?action=download&usetoken=" + (Settings.UseFreeleechToken ? "1" : "0") + "&id=";
protected virtual string DetailsUrl => BaseUrl + "torrents.php?torrentid=";
@ -40,10 +39,6 @@ namespace NzbDrone.Core.Indexers.Gazelle
private IEnumerable<IndexerRequest> GetRequest(string searchParameters)
{
AuthCookieCache = GetCookies();
Authenticate();
var filter = "";
if (searchParameters == null)
{
@ -51,91 +46,17 @@ namespace NzbDrone.Core.Indexers.Gazelle
var request =
new IndexerRequest(
$"{APIUrl}?action=browse{searchParameters}{filter}",
$"{APIUrl}?{searchParameters}{filter}",
HttpAccept.Json);
var cookies = AuthCookieCache;
foreach (var cookie in cookies)
{
request.HttpRequest.Cookies[cookie.Key] = cookie.Value;
}
yield return request;
}
private GazelleAuthResponse GetIndex(IDictionary<string, string> cookies)
{
var indexRequestBuilder = new HttpRequestBuilder($"{APIUrl}?action=index")
{
LogResponseContent = true
};
indexRequestBuilder.SetCookies(cookies);
indexRequestBuilder.Method = HttpMethod.POST;
var authIndexRequest = indexRequestBuilder
.Accept(HttpAccept.Json)
.Build();
var indexResponse = HttpClient.Execute(authIndexRequest);
var result = Json.Deserialize<GazelleAuthResponse>(indexResponse.Content);
return result;
}
private void Authenticate()
{
var requestBuilder = new HttpRequestBuilder(LoginUrl)
{
LogResponseContent = true
};
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var cookies = AuthCookieCache;
if (cookies == null)
{
AuthCookieCache = null;
var authLoginRequest = requestBuilder
.AddFormParameter("username", Settings.Username)
.AddFormParameter("password", Settings.Password)
.AddFormParameter("keeplogged", "1")
.SetHeader("Content-Type", "multipart/form-data")
.Accept(HttpAccept.Json)
.Build();
var response = HttpClient.Execute(authLoginRequest);
cookies = response.GetCookies();
AuthCookieCache = cookies;
CookiesUpdater(cookies, DateTime.Now + TimeSpan.FromDays(30));
}
var index = GetIndex(cookies);
if (index == null || index.Status.IsNullOrWhiteSpace() || index.Status != "success")
{
Logger.Debug("Gazelle authentication failed.");
AuthCookieCache = null;
CookiesUpdater(null, null);
throw new Exception("Failed to authenticate with Gazelle.");
}
Logger.Debug("Gazelle authentication succeeded.");
Settings.AuthKey = index.Response.Authkey;
Settings.PassKey = index.Response.Passkey;
}
private string GetBasicSearchParameters(string searchTerm, int[] categories)
{
var searchString = GetSearchTerm(searchTerm);
var parameters = "&action=browse&order_by=time&order_way=desc";
var parameters = "action=browse&order_by=time&order_way=desc";
if (!string.IsNullOrWhiteSpace(searchString))
{

@ -22,6 +22,7 @@ namespace NzbDrone.Core.Indexers
protected const int MaxNumResultsPerQuery = 1000;
protected readonly IHttpClient _httpClient;
public IDictionary<string, string> Cookies { get; set; }
public override bool SupportsRss => true;
public override bool SupportsSearch => true;
@ -111,6 +112,23 @@ namespace NzbDrone.Core.Indexers
return generator;
}
protected IDictionary<string, string> GetCookies()
{
var cookies = _indexerStatusService.GetIndexerCookies(Definition.Id);
var expiration = _indexerStatusService.GetIndexerCookiesExpirationDate(Definition.Id);
if (expiration < DateTime.Now)
{
cookies = null;
}
return cookies;
}
protected void UpdateCookies(IDictionary<string, string> cookies, DateTime? expiration)
{
_indexerStatusService.UpdateCookies(Definition.Id, cookies, expiration);
}
protected virtual IndexerPageableQueryResult FetchReleases(Func<IIndexerRequestGenerator, IndexerPageableRequestChain> pageableRequestChainSelector, bool isRecent = false)
{
var releases = new List<ReleaseInfo>();
@ -333,6 +351,15 @@ namespace NzbDrone.Core.Indexers
}
}
protected virtual bool CheckIfLoginNeeded(HttpResponse httpResponse)
{
return false;
}
protected virtual void DoLogin()
{
}
protected virtual IndexerResponse FetchIndexerResponse(IndexerRequest request)
{
_logger.Debug("Downloading Feed " + request.HttpRequest.ToString(false));
@ -342,7 +369,17 @@ namespace NzbDrone.Core.Indexers
request.HttpRequest.RateLimit = RateLimit;
}
request.HttpRequest.AllowAutoRedirect = true;
request.HttpRequest.AllowAutoRedirect = false;
Cookies = GetCookies();
if (Cookies != null)
{
foreach (var cookie in Cookies)
{
request.HttpRequest.Cookies.Add(cookie.Key, cookie.Value);
}
}
var stopWatch = Stopwatch.StartNew();
@ -350,6 +387,23 @@ namespace NzbDrone.Core.Indexers
stopWatch.Stop();
// Check reponse to see if auth is needed, if needed try again
if (CheckIfLoginNeeded(response))
{
DoLogin();
request.HttpRequest.Cookies.Clear();
if (Cookies != null)
{
foreach (var cookie in Cookies)
{
request.HttpRequest.Cookies.Add(cookie.Key, cookie.Value);
}
}
response = _httpClient.Execute(request.HttpRequest);
}
return new IndexerResponse(request, response, stopWatch.ElapsedMilliseconds);
}

Loading…
Cancel
Save