diff --git a/frontend/src/Indexer/Index/Table/MovieIndexRow.css b/frontend/src/Indexer/Index/Table/IndexerIndexRow.css
similarity index 87%
rename from frontend/src/Indexer/Index/Table/MovieIndexRow.css
rename to frontend/src/Indexer/Index/Table/IndexerIndexRow.css
index 308bbab2b..cb40642c7 100644
--- a/frontend/src/Indexer/Index/Table/MovieIndexRow.css
+++ b/frontend/src/Indexer/Index/Table/IndexerIndexRow.css
@@ -56,8 +56,8 @@
margin-top: 0;
}
-.externalLinks {
- margin: 0 2px;
- width: 22px;
- text-align: center;
+.externalLink {
+ composes: link from '~Components/Link/Link.css';
+
+ color: $textColor;
}
diff --git a/frontend/src/Indexer/Index/Table/MovieIndexRow.js b/frontend/src/Indexer/Index/Table/IndexerIndexRow.js
similarity index 95%
rename from frontend/src/Indexer/Index/Table/MovieIndexRow.js
rename to frontend/src/Indexer/Index/Table/IndexerIndexRow.js
index 64c03738c..40c54d3b2 100644
--- a/frontend/src/Indexer/Index/Table/MovieIndexRow.js
+++ b/frontend/src/Indexer/Index/Table/IndexerIndexRow.js
@@ -14,9 +14,9 @@ import translate from 'Utilities/String/translate';
import CapabilitiesLabel from './CapabilitiesLabel';
import IndexerStatusCell from './IndexerStatusCell';
import ProtocolLabel from './ProtocolLabel';
-import styles from './MovieIndexRow.css';
+import styles from './IndexerIndexRow.css';
-class MovieIndexRow extends Component {
+class IndexerIndexRow extends Component {
//
// Lifecycle
@@ -61,6 +61,7 @@ class MovieIndexRow extends Component {
const {
id,
name,
+ baseUrl,
enable,
tags,
protocol,
@@ -213,8 +214,10 @@ class MovieIndexRow extends Component {
className={styles[column.name]}
>
("Indexers").RegisterModel()
.Ignore(x => x.ImplementationName)
+ .Ignore(i => i.BaseUrl)
.Ignore(i => i.Protocol)
.Ignore(i => i.Privacy)
.Ignore(i => i.SupportsRss)
diff --git a/src/NzbDrone.Core/Indexers/Definitions/Cardigann/Cardigann.cs b/src/NzbDrone.Core/Indexers/Definitions/Cardigann/Cardigann.cs
index 9b72100be..dac347dd7 100644
--- a/src/NzbDrone.Core/Indexers/Definitions/Cardigann/Cardigann.cs
+++ b/src/NzbDrone.Core/Indexers/Definitions/Cardigann/Cardigann.cs
@@ -15,7 +15,7 @@ public class Cardigann : HttpIndexerBase
private readonly IIndexerDefinitionUpdateService _definitionService;
public override string Name => "Cardigann";
- public override string BaseUrl => throw new System.NotImplementedException();
+ public override string BaseUrl => "";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
@@ -76,6 +76,24 @@ private IndexerDefinition GetDefinition(CardigannMetaDefinition definition)
};
}
+ protected override bool CheckIfLoginNeeded(HttpResponse httpResponse)
+ {
+ var generator = (CardigannRequestGenerator)GetRequestGenerator();
+
+ SetCookieFunctions(generator);
+
+ return generator.CheckIfLoginIsNeeded(httpResponse);
+ }
+
+ protected override void DoLogin()
+ {
+ var generator = (CardigannRequestGenerator)GetRequestGenerator();
+
+ SetCookieFunctions(generator);
+
+ generator.DoLogin();
+ }
+
protected override void Test(List failures)
{
base.Test(failures);
diff --git a/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannRequestGenerator.cs
index 1eb4eac7f..850285e37 100644
--- a/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannRequestGenerator.cs
+++ b/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannRequestGenerator.cs
@@ -155,15 +155,10 @@ private Dictionary GetQueryVariableDefaults(SearchCriteriaBase s
return variables;
}
- private void Authenticate()
+ public void DoLogin()
{
var login = _definition.Login;
- if (login == null || TestLogin())
- {
- return;
- }
-
if (login.Method == "post")
{
var pairs = new Dictionary();
@@ -725,7 +720,7 @@ protected string GetRedirectDomainHint(string requestUrl, string redirectUrl)
protected string GetRedirectDomainHint(HttpResponse result) => GetRedirectDomainHint(result.Request.Url.ToString(), result.Headers.GetSingleValue("Location"));
- protected bool CheckIfLoginIsNeeded(HttpResponse response, IHtmlDocument document)
+ public bool CheckIfLoginIsNeeded(HttpResponse response)
{
if (response.HasHttpRedirect)
{
@@ -745,6 +740,9 @@ protected bool CheckIfLoginIsNeeded(HttpResponse response, IHtmlDocument documen
return false;
}
+ var parser = new HtmlParser();
+ var document = parser.ParseDocument(response.Content);
+
if (_definition.Login.Test.Selector != null)
{
var selection = document.QuerySelectorAll(_definition.Login.Test.Selector);
@@ -759,13 +757,6 @@ protected bool CheckIfLoginIsNeeded(HttpResponse response, IHtmlDocument documen
private IEnumerable GetRequest(Dictionary variables)
{
- Cookies = GetCookies();
-
- if (Cookies == null || !Cookies.Any())
- {
- Authenticate();
- }
-
var search = _definition.Search;
var mappedCategories = MapTorznabCapsToTrackers((int[])variables[".Query.Categories"]);
@@ -890,14 +881,6 @@ private IEnumerable GetRequest(Dictionary variab
}
}
- if (Cookies != null)
- {
- foreach (var cookie in Cookies)
- {
- request.HttpRequest.Cookies.Add(cookie.Key, cookie.Value);
- }
- }
-
request.HttpRequest.Method = method;
yield return request;
diff --git a/src/NzbDrone.Core/Indexers/Definitions/Gazelle/Gazelle.cs b/src/NzbDrone.Core/Indexers/Definitions/Gazelle/Gazelle.cs
index 091155af1..9dda57ff7 100644
--- a/src/NzbDrone.Core/Indexers/Definitions/Gazelle/Gazelle.cs
+++ b/src/NzbDrone.Core/Indexers/Definitions/Gazelle/Gazelle.cs
@@ -72,8 +72,6 @@ protected override void DoLogin()
cookies = response.GetCookies();
- Cookies = cookies;
-
UpdateCookies(cookies, DateTime.Now + TimeSpan.FromDays(30));
_logger.Debug("Gazelle authentication succeeded.");
diff --git a/src/NzbDrone.Core/Indexers/Definitions/HDTorrents.cs b/src/NzbDrone.Core/Indexers/Definitions/HDTorrents.cs
index f1e115dd1..8eabe0473 100644
--- a/src/NzbDrone.Core/Indexers/Definitions/HDTorrents.cs
+++ b/src/NzbDrone.Core/Indexers/Definitions/HDTorrents.cs
@@ -65,7 +65,6 @@ protected override void DoLogin()
var response = _httpClient.Execute(authLoginRequest);
cookies = response.GetCookies();
- Cookies = cookies;
UpdateCookies(cookies, DateTime.Now + TimeSpan.FromDays(30));
_logger.Debug("HDTorrents authentication succeeded.");
diff --git a/src/NzbDrone.Core/Indexers/Definitions/IPTorrents.cs b/src/NzbDrone.Core/Indexers/Definitions/IPTorrents.cs
index c4aa05f5d..963f23d6f 100644
--- a/src/NzbDrone.Core/Indexers/Definitions/IPTorrents.cs
+++ b/src/NzbDrone.Core/Indexers/Definitions/IPTorrents.cs
@@ -304,6 +304,7 @@ public IList ParseResponse(IndexerResponse indexerResponse)
Title = title,
Guid = details.AbsoluteUri,
DownloadUrl = link.AbsoluteUri,
+ InfoUrl = details.AbsoluteUri,
PublishDate = publishDate,
Category = cat,
Size = size,
diff --git a/src/NzbDrone.Core/Indexers/Definitions/Newznab/Newznab.cs b/src/NzbDrone.Core/Indexers/Definitions/Newznab/Newznab.cs
index a971ed4dd..e3de9680b 100644
--- a/src/NzbDrone.Core/Indexers/Definitions/Newznab/Newznab.cs
+++ b/src/NzbDrone.Core/Indexers/Definitions/Newznab/Newznab.cs
@@ -16,7 +16,7 @@ public class Newznab : HttpIndexerBase
private readonly INewznabCapabilitiesProvider _capabilitiesProvider;
public override string Name => "Newznab";
- public override string BaseUrl => Settings.BaseUrl;
+ public override string BaseUrl => GetBaseUrlFromSettings();
public override bool FollowRedirect => true;
public override DownloadProtocol Protocol => DownloadProtocol.Usenet;
@@ -40,6 +40,18 @@ public override IParseIndexerResponse GetParser()
return new NewznabRssParser(Settings);
}
+ public string GetBaseUrlFromSettings()
+ {
+ var baseUrl = "";
+
+ if (Definition == null || Settings == null || Settings.Categories == null)
+ {
+ return baseUrl;
+ }
+
+ return Settings.BaseUrl;
+ }
+
public IndexerCapabilities GetCapabilitiesFromSettings()
{
var caps = new IndexerCapabilities();
diff --git a/src/NzbDrone.Core/Indexers/Definitions/TorrentDay.cs b/src/NzbDrone.Core/Indexers/Definitions/TorrentDay.cs
index 9cb2c9fd3..92c4c48df 100644
--- a/src/NzbDrone.Core/Indexers/Definitions/TorrentDay.cs
+++ b/src/NzbDrone.Core/Indexers/Definitions/TorrentDay.cs
@@ -242,6 +242,7 @@ public IList ParseResponse(IndexerResponse indexerResponse)
Title = title,
Guid = details.AbsoluteUri,
DownloadUrl = link.AbsoluteUri,
+ InfoUrl = details.AbsoluteUri,
PublishDate = publishDate,
Category = _categories.MapTrackerCatToNewznab(row.c.ToString()),
Size = (long)row.size,
diff --git a/src/NzbDrone.Core/Indexers/Definitions/TorrentLeech.cs b/src/NzbDrone.Core/Indexers/Definitions/TorrentLeech.cs
index 56e30a12e..3b1e54c8d 100644
--- a/src/NzbDrone.Core/Indexers/Definitions/TorrentLeech.cs
+++ b/src/NzbDrone.Core/Indexers/Definitions/TorrentLeech.cs
@@ -66,7 +66,6 @@ protected override void DoLogin()
var response = _httpClient.Execute(authLoginRequest);
cookies = response.GetCookies();
- Cookies = cookies;
UpdateCookies(cookies, DateTime.Now + TimeSpan.FromDays(30));
_logger.Debug("TorrentLeech authentication succeeded.");
diff --git a/src/NzbDrone.Core/Indexers/Definitions/Torznab/Torznab.cs b/src/NzbDrone.Core/Indexers/Definitions/Torznab/Torznab.cs
index 557fd71f5..6aab1a176 100644
--- a/src/NzbDrone.Core/Indexers/Definitions/Torznab/Torznab.cs
+++ b/src/NzbDrone.Core/Indexers/Definitions/Torznab/Torznab.cs
@@ -17,7 +17,7 @@ public class Torznab : HttpIndexerBase
private readonly INewznabCapabilitiesProvider _capabilitiesProvider;
public override string Name => "Torznab";
- public override string BaseUrl => Settings.BaseUrl;
+ public override string BaseUrl => "";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
diff --git a/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs b/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs
index e202dbbfc..d3d2d7078 100644
--- a/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs
+++ b/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs
@@ -136,7 +136,7 @@ protected IIndexerRequestGenerator SetCookieFunctions(IIndexerRequestGenerator g
generator.CookiesUpdater = (cookies, expiration) =>
{
- _indexerStatusService.UpdateCookies(Definition.Id, cookies, expiration);
+ UpdateCookies(cookies, expiration);
};
return generator;
@@ -156,6 +156,7 @@ protected IDictionary GetCookies()
protected void UpdateCookies(IDictionary cookies, DateTime? expiration)
{
+ Cookies = cookies;
_indexerStatusService.UpdateCookies(Definition.Id, cookies, expiration);
}
@@ -434,6 +435,8 @@ protected virtual IndexerResponse FetchIndexerResponse(IndexerRequest request)
response = _httpClient.Execute(request.HttpRequest);
}
+ UpdateCookies(Cookies, DateTime.Now + TimeSpan.FromDays(30));
+
return new IndexerResponse(request, response, stopWatch.ElapsedMilliseconds);
}
diff --git a/src/NzbDrone.Core/Indexers/IIndexer.cs b/src/NzbDrone.Core/Indexers/IIndexer.cs
index ce19c9dec..e9f6a94de 100644
--- a/src/NzbDrone.Core/Indexers/IIndexer.cs
+++ b/src/NzbDrone.Core/Indexers/IIndexer.cs
@@ -10,6 +10,7 @@ public interface IIndexer : IProvider
bool SupportsSearch { get; }
IndexerCapabilities Capabilities { get; }
+ string BaseUrl { get; }
DownloadProtocol Protocol { get; }
IndexerPrivacy Privacy { get; }
diff --git a/src/NzbDrone.Core/Indexers/IndexerDefinition.cs b/src/NzbDrone.Core/Indexers/IndexerDefinition.cs
index fba0eadf6..31f42d5ee 100644
--- a/src/NzbDrone.Core/Indexers/IndexerDefinition.cs
+++ b/src/NzbDrone.Core/Indexers/IndexerDefinition.cs
@@ -7,6 +7,7 @@ namespace NzbDrone.Core.Indexers
{
public class IndexerDefinition : ProviderDefinition
{
+ public string BaseUrl { get; set; }
public DownloadProtocol Protocol { get; set; }
public IndexerPrivacy Privacy { get; set; }
public bool SupportsRss { get; set; }
diff --git a/src/NzbDrone.Core/Indexers/IndexerFactory.cs b/src/NzbDrone.Core/Indexers/IndexerFactory.cs
index 108d46bfb..4af697fdb 100644
--- a/src/NzbDrone.Core/Indexers/IndexerFactory.cs
+++ b/src/NzbDrone.Core/Indexers/IndexerFactory.cs
@@ -52,6 +52,7 @@ public override List All()
var settings = (CardigannSettings)definition.Settings;
var defFile = _definitionService.GetDefinition(settings.DefinitionFile);
definition.ExtraFields = defFile.Settings;
+ definition.BaseUrl = defFile.Links.First();
definition.Privacy = defFile.Type == "private" ? IndexerPrivacy.Private : IndexerPrivacy.Public;
definition.Capabilities = new IndexerCapabilities();
definition.Capabilities.ParseCardigannSearchModes(defFile.Caps.Modes);
@@ -71,6 +72,7 @@ public override IndexerDefinition Get(int id)
var settings = (CardigannSettings)definition.Settings;
var defFile = _definitionService.GetDefinition(settings.DefinitionFile);
definition.ExtraFields = defFile.Settings;
+ definition.BaseUrl = defFile.Links.First();
definition.Privacy = defFile.Type == "private" ? IndexerPrivacy.Private : IndexerPrivacy.Public;
definition.Capabilities = new IndexerCapabilities();
definition.Capabilities.ParseCardigannSearchModes(defFile.Caps.Modes);
@@ -158,6 +160,7 @@ public override void SetProviderCharacteristics(IIndexer provider, IndexerDefini
//We want to use the definition Caps and Privacy for Cardigann instead of the provider.
if (definition.Implementation != typeof(Cardigann.Cardigann).Name)
{
+ definition.BaseUrl = provider.BaseUrl;
definition.Privacy = provider.Privacy;
definition.Capabilities = provider.Capabilities;
}
diff --git a/src/Prowlarr.Api.V1/Indexers/IndexerResource.cs b/src/Prowlarr.Api.V1/Indexers/IndexerResource.cs
index dfdf02b4a..c5dcc2c26 100644
--- a/src/Prowlarr.Api.V1/Indexers/IndexerResource.cs
+++ b/src/Prowlarr.Api.V1/Indexers/IndexerResource.cs
@@ -10,6 +10,7 @@ namespace Prowlarr.Api.V1.Indexers
{
public class IndexerResource : ProviderResource
{
+ public string BaseUrl { get; set; }
public bool Enable { get; set; }
public bool SupportsRss { get; set; }
public bool SupportsSearch { get; set; }
@@ -49,6 +50,7 @@ public override IndexerResource ToResource(IndexerDefinition definition)
}
}
+ resource.BaseUrl = definition.BaseUrl;
resource.Enable = definition.Enable;
resource.SupportsRss = definition.SupportsRss;
resource.SupportsSearch = definition.SupportsSearch;
@@ -85,6 +87,7 @@ public override IndexerDefinition ToModel(IndexerResource resource)
}
definition.Enable = resource.Enable;
+ definition.BaseUrl = resource.BaseUrl;
definition.Priority = resource.Priority;
definition.Privacy = resource.Privacy;
definition.Added = resource.Added;