mirror of https://github.com/Jackett/Jackett
I have a feeling I'm breaking the world and bringing the apocalypse
It's quite hard to encapsulate something this large. This refactor contains multiple attacks on the current architecture and is changing things that were probably created quite a while back then. Luckily this was done in increments so it mustn't be that impossible to recall what has been done. I just need to relax my memory a little bit. So the basic idea was quite simple. Let's distingush metas and normal indexers a little bit more. Both of them were originating from BaseIndexer, however very little of the functionality was actually shared between them. Actually quite a few things made it even harder to implement a different kind of indexer, especially for a newcomer for both Jackett and C#. Then in order to further reduce whatever was encapsulated in any kind of, a couple things had to be changed. Like CardigannIndexer, which probably had quite a mindshift change. IndexerManager and the configuration management were also encapsulated and refactored, and now I have a feeling that although the code could be improved, at least the responsibilities of services and what they actually do is now clearer. Anyhow, it would be safe to assume that I will not be able to go step-by-step and define everything that has been changed. I'm sorry.
This commit is contained in:
parent
35103206cf
commit
9e3076dde6
|
@ -94,8 +94,14 @@
|
|||
<MonoDevelop>
|
||||
<Properties>
|
||||
<Policies>
|
||||
<TextStylePolicy inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
|
||||
<CSharpFormattingPolicy IndentSwitchBody="True" IndentBlocksInsideExpressions="True" AnonymousMethodBraceStyle="NextLine" PropertyBraceStyle="NextLine" PropertyGetBraceStyle="NextLine" PropertySetBraceStyle="NextLine" EventBraceStyle="NextLine" EventAddBraceStyle="NextLine" EventRemoveBraceStyle="NextLine" StatementBraceStyle="NextLine" ElseNewLinePlacement="NewLine" CatchNewLinePlacement="NewLine" FinallyNewLinePlacement="NewLine" WhileNewLinePlacement="DoNotCare" ArrayInitializerWrapping="DoNotChange" ArrayInitializerBraceStyle="NextLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
|
||||
<TextStylePolicy TabWidth="4" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" FileWidth="80" TabsToSpaces="True" scope="text/x-csharp">
|
||||
<inheritsSet />
|
||||
<inheritsScope />
|
||||
</TextStylePolicy>
|
||||
<CSharpFormattingPolicy IndentBlock="True" IndentBraces="False" IndentSwitchSection="False" IndentSwitchCaseSection="True" LabelPositioning="OneLess" NewLinesForBracesInTypes="True" NewLinesForBracesInMethods="True" NewLinesForBracesInProperties="False" NewLinesForBracesInAccessors="False" NewLinesForBracesInAnonymousMethods="False" NewLinesForBracesInControlBlocks="False" NewLinesForBracesInAnonymousTypes="False" NewLinesForBracesInObjectCollectionArrayInitializers="False" NewLinesForBracesInLambdaExpressionBody="False" NewLineForElse="False" NewLineForCatch="False" NewLineForFinally="False" NewLineForMembersInObjectInit="False" NewLineForMembersInAnonymousTypes="False" NewLineForClausesInQuery="False" SpacingAfterMethodDeclarationName="True" SpaceWithinMethodDeclarationParenthesis="False" SpaceBetweenEmptyMethodDeclarationParentheses="False" SpaceAfterMethodCallName="True" SpaceWithinMethodCallParentheses="False" SpaceBetweenEmptyMethodCallParentheses="False" SpaceAfterControlFlowStatementKeyword="True" SpaceWithinExpressionParentheses="False" SpaceWithinCastParentheses="False" SpaceWithinOtherParentheses="False" SpaceAfterCast="False" SpacesIgnoreAroundVariableDeclaration="False" SpaceBeforeOpenSquareBracket="True" SpaceBetweenEmptySquareBrackets="False" SpaceWithinSquareBrackets="False" SpaceAfterColonInBaseTypeDeclaration="True" SpaceAfterComma="True" SpaceAfterDot="False" SpaceAfterSemicolonsInForStatement="True" SpaceBeforeColonInBaseTypeDeclaration="True" SpaceBeforeComma="False" SpaceBeforeDot="False" SpaceBeforeSemicolonsInForStatement="False" SpacingAroundBinaryOperator="Single" WrappingPreserveSingleLine="True" WrappingKeepStatementsOnSingleLine="True" PlaceSystemDirectiveFirst="True" scope="text/x-csharp">
|
||||
<inheritsSet />
|
||||
<inheritsScope />
|
||||
</CSharpFormattingPolicy>
|
||||
</Policies>
|
||||
</Properties>
|
||||
</MonoDevelop>
|
||||
|
|
|
@ -66,9 +66,9 @@ Global
|
|||
GlobalSection(MonoDevelopProperties) = preSolution
|
||||
Policies = $0
|
||||
$0.TextStylePolicy = $1
|
||||
$1.inheritsSet = VisualStudio
|
||||
$1.inheritsScope = text/plain
|
||||
$1.scope = text/x-csharp
|
||||
$1.TabsToSpaces = True
|
||||
$1.EolMarker = Unix
|
||||
$0.CSharpFormattingPolicy = $2
|
||||
$2.IndentSwitchBody = True
|
||||
$2.IndentBlocksInsideExpressions = True
|
||||
|
@ -94,8 +94,13 @@ Global
|
|||
$2.BeforeDelegateDeclarationParentheses = False
|
||||
$2.NewParentheses = False
|
||||
$2.SpacesBeforeBrackets = False
|
||||
$2.inheritsSet = Mono
|
||||
$2.inheritsScope = text/x-csharp
|
||||
$2.scope = text/x-csharp
|
||||
$2.IndentSwitchSection = True
|
||||
$2.SpacingAfterMethodDeclarationName = False
|
||||
$2.SpaceAfterMethodCallName = False
|
||||
$2.SpaceBeforeOpenSquareBracket = False
|
||||
$0.DotNetNamingPolicy = $3
|
||||
$3.DirectoryNamespaceAssociation = PrefixedHierarchical
|
||||
$0.StandardHeader = $4
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -205,7 +205,7 @@ namespace Jackett.Controllers
|
|||
baseIndexer.ResetBaseConfig();
|
||||
if (ex is ExceptionWithConfigData)
|
||||
{
|
||||
jsonReply["config"] = ((ExceptionWithConfigData)ex).ConfigData.ToJson(null,false);
|
||||
jsonReply["config"] = ((ExceptionWithConfigData)ex).ConfigData.ToJson(null, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -431,7 +431,7 @@ namespace Jackett.Controllers
|
|||
Engine.Server.Start();
|
||||
})).Start();
|
||||
}
|
||||
|
||||
|
||||
if (saveDir != Engine.Server.Config.BlackholeDir)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(saveDir))
|
||||
|
@ -498,7 +498,7 @@ namespace Jackett.Controllers
|
|||
|
||||
var queryStr = value.Query;
|
||||
if (queryStr != null)
|
||||
{
|
||||
{
|
||||
var seasonMatch = Regex.Match(queryStr, @"S(\d{2,4})");
|
||||
if (seasonMatch.Success)
|
||||
{
|
||||
|
@ -514,7 +514,7 @@ namespace Jackett.Controllers
|
|||
}
|
||||
queryStr = queryStr.Trim();
|
||||
}
|
||||
|
||||
|
||||
|
||||
stringQuery.SearchTerm = queryStr;
|
||||
stringQuery.Categories = value.Category == 0 ? new int[0] : new int[1] { value.Category };
|
||||
|
@ -556,9 +556,7 @@ namespace Jackett.Controllers
|
|||
query = imdbQuery;
|
||||
|
||||
var searchResults = indexer.ResultsForQuery(query).Result;
|
||||
searchResults = indexer.CleanLinks(searchResults);
|
||||
cacheService.CacheRssResults(indexer, searchResults);
|
||||
searchResults = indexer.FilterResults(query, searchResults);
|
||||
|
||||
foreach (var result in searchResults)
|
||||
{
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace Jackett.Controllers
|
|||
var jsonReply = new JObject();
|
||||
try
|
||||
{
|
||||
var indexer = indexerService.GetIndexer(indexerID);
|
||||
var indexer = indexerService.GetWebIndexer(indexerID);
|
||||
if (!indexer.IsConfigured)
|
||||
{
|
||||
logger.Warn(string.Format("Rejected a request to {0} which is unconfigured.", indexer.DisplayName));
|
||||
|
@ -48,8 +48,6 @@ namespace Jackett.Controllers
|
|||
throw new Exception("Incorrect API key");
|
||||
|
||||
var remoteFile = new Uri(Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(path)), UriKind.RelativeOrAbsolute);
|
||||
remoteFile = indexer.UncleanLink(remoteFile);
|
||||
|
||||
var downloadBytes = await indexer.Download(remoteFile);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Engine.Server.Config.BlackholeDir))
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace Jackett.Controllers
|
|||
{
|
||||
try
|
||||
{
|
||||
var indexer = indexerService.GetIndexer(indexerID);
|
||||
var indexer = indexerService.GetWebIndexer(indexerID);
|
||||
|
||||
if (!indexer.IsConfigured)
|
||||
{
|
||||
|
@ -48,20 +48,19 @@ namespace Jackett.Controllers
|
|||
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
||||
|
||||
var target = new Uri(path, UriKind.RelativeOrAbsolute);
|
||||
target = indexer.UncleanLink(target);
|
||||
|
||||
var downloadBytes = await indexer.Download(target);
|
||||
|
||||
// This will fix torrents where the keys are not sorted, and thereby not supported by Sonarr.
|
||||
var torrentDictionary = BEncodedDictionary.DecodeTorrent(downloadBytes);
|
||||
downloadBytes = torrentDictionary.Encode();
|
||||
|
||||
char[] invalidChars = System.IO.Path.GetInvalidFileNameChars();
|
||||
for(int i=0;i<file.Count();i++)
|
||||
if(invalidChars.Contains(file[i])) {
|
||||
file = file.Remove(i, 1).Insert(i, " ");
|
||||
}
|
||||
|
||||
char[] invalidChars = System.IO.Path.GetInvalidFileNameChars();
|
||||
for (int i = 0; i < file.Count(); i++)
|
||||
if (invalidChars.Contains(file[i]))
|
||||
{
|
||||
file = file.Remove(i, 1).Insert(i, " ");
|
||||
}
|
||||
|
||||
var result = new HttpResponseMessage(HttpStatusCode.OK);
|
||||
result.Content = new ByteArrayContent(downloadBytes);
|
||||
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-bittorrent");
|
||||
|
|
|
@ -15,6 +15,7 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using Jackett.Indexers;
|
||||
|
||||
namespace Jackett.Controllers
|
||||
{
|
||||
|
@ -38,7 +39,7 @@ namespace Jackett.Controllers
|
|||
};
|
||||
|
||||
torznabQuery.ExpandCatsToSubCats();
|
||||
return torznabQuery.Categories;
|
||||
return torznabQuery.Categories;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +56,7 @@ namespace Jackett.Controllers
|
|||
public async Task<HttpResponseMessage> Call(string indexerID, [FromUri]TorrentPotatoRequest request)
|
||||
{
|
||||
var indexer = indexerService.GetIndexer(indexerID);
|
||||
|
||||
|
||||
var allowBadApiDueToDebug = false;
|
||||
#if DEBUG
|
||||
allowBadApiDueToDebug = Debugger.IsAttached;
|
||||
|
@ -73,7 +74,8 @@ namespace Jackett.Controllers
|
|||
return Request.CreateResponse(HttpStatusCode.Forbidden, "This indexer is not configured.");
|
||||
}
|
||||
|
||||
if (!indexer.TorznabCaps.Categories.Select(c => c.ID).Any(i => MOVIE_CATS.Contains(i))){
|
||||
if (!indexer.TorznabCaps.Categories.Select(c => c.ID).Any(i => MOVIE_CATS.Contains(i)))
|
||||
{
|
||||
logger.Warn(string.Format("Rejected a request to {0} which does not support searching for movies.", indexer.DisplayName));
|
||||
return Request.CreateResponse(HttpStatusCode.Forbidden, "This indexer does not support movies.");
|
||||
}
|
||||
|
@ -92,7 +94,7 @@ namespace Jackett.Controllers
|
|||
|
||||
var torznabQuery = new TorznabQuery()
|
||||
{
|
||||
ApiKey = request.passkey,
|
||||
ApiKey = request.passkey,
|
||||
Categories = MOVIE_CATS,
|
||||
SearchTerm = request.search,
|
||||
ImdbID = request.imdbid,
|
||||
|
@ -102,10 +104,7 @@ namespace Jackett.Controllers
|
|||
IEnumerable<ReleaseInfo> releases = new List<ReleaseInfo>();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(torznabQuery.SanitizedSearchTerm))
|
||||
{
|
||||
releases = await indexer.ResultsForQuery(torznabQuery);
|
||||
releases = indexer.CleanLinks(releases);
|
||||
}
|
||||
|
||||
// Cache non query results
|
||||
if (string.IsNullOrEmpty(torznabQuery.SanitizedSearchTerm))
|
||||
|
@ -113,7 +112,6 @@ namespace Jackett.Controllers
|
|||
cacheService.CacheRssResults(indexer, releases);
|
||||
}
|
||||
|
||||
releases = indexer.FilterResults(torznabQuery, releases);
|
||||
var serverUrl = string.Format("{0}://{1}:{2}{3}", Request.RequestUri.Scheme, Request.RequestUri.Host, Request.RequestUri.Port, serverService.BasePath());
|
||||
var potatoResponse = new TorrentPotatoResponse();
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ using System.Threading.Tasks;
|
|||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using System.Xml.Linq;
|
||||
using Jackett.Indexers;
|
||||
|
||||
namespace Jackett.Controllers
|
||||
{
|
||||
|
@ -57,7 +58,7 @@ namespace Jackett.Controllers
|
|||
{
|
||||
var indexer = indexerService.GetIndexer(indexerID);
|
||||
var torznabQuery = TorznabQuery.FromHttpQuery(HttpUtility.ParseQueryString(Request.RequestUri.Query));
|
||||
|
||||
|
||||
if (string.Equals(torznabQuery.QueryType, "caps", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return new HttpResponseMessage()
|
||||
|
@ -113,7 +114,6 @@ namespace Jackett.Controllers
|
|||
}
|
||||
|
||||
var releases = await indexer.ResultsForQuery(torznabQuery);
|
||||
releases = indexer.CleanLinks(releases);
|
||||
|
||||
// Some trackers do not keep their clocks up to date and can be ~20 minutes out!
|
||||
foreach (var release in releases.Where(r => r.PublishDate > DateTime.Now))
|
||||
|
@ -122,26 +122,28 @@ namespace Jackett.Controllers
|
|||
}
|
||||
|
||||
// Some trackers do not support multiple category filtering so filter the releases that match manually.
|
||||
var filteredReleases = releases = indexer.FilterResults(torznabQuery, releases);
|
||||
int? newItemCount = null;
|
||||
|
||||
// Cache non query results
|
||||
if (string.IsNullOrEmpty(torznabQuery.SanitizedSearchTerm))
|
||||
{
|
||||
newItemCount = cacheService.GetNewItemCount(indexer, filteredReleases);
|
||||
newItemCount = cacheService.GetNewItemCount(indexer, releases);
|
||||
cacheService.CacheRssResults(indexer, releases);
|
||||
}
|
||||
|
||||
// Log info
|
||||
var logBuilder = new StringBuilder();
|
||||
if (newItemCount != null) {
|
||||
if (newItemCount != null)
|
||||
{
|
||||
logBuilder.AppendFormat(string.Format("Found {0} ({1} new) releases from {2}", releases.Count(), newItemCount, indexer.DisplayName));
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
logBuilder.AppendFormat(string.Format("Found {0} releases from {1}", releases.Count(), indexer.DisplayName));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(torznabQuery.SanitizedSearchTerm)) {
|
||||
if (!string.IsNullOrWhiteSpace(torznabQuery.SanitizedSearchTerm))
|
||||
{
|
||||
logBuilder.AppendFormat(" for: {0}", torznabQuery.GetQueryString());
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ using System.Web;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class SevenTor : BaseIndexer
|
||||
public class SevenTor : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "ucp.php?mode=login"; } }
|
||||
string SearchUrl { get { return SiteLink + "search.php"; } }
|
||||
|
@ -29,12 +29,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public SevenTor(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public SevenTor(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "7tor",
|
||||
description: null,
|
||||
link: "https://7tor.org/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Jackett.Indexers
|
|||
/// <summary>
|
||||
/// Provider for Abnormal Private French Tracker
|
||||
/// </summary>
|
||||
public class Abnormal : BaseIndexer
|
||||
public class Abnormal : BaseCachingWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "torrents.php"; } }
|
||||
|
@ -43,13 +43,13 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Abnormal(IIndexerManagerService i, IWebClient w, Logger l, IProtectionService ps)
|
||||
public Abnormal(IIndexerConfigurationService configService, IWebClient w, Logger l, IProtectionService ps)
|
||||
: base(
|
||||
name: "Abnormal",
|
||||
description: "General French Private Tracker",
|
||||
link: "https://abnormal.ws/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
@ -117,7 +117,8 @@ namespace Jackett.Indexers
|
|||
// emulatedBrowserHeaders.Add("Accept-Encoding", "gzip, deflate");
|
||||
|
||||
// If we want to simulate a browser
|
||||
if (ConfigData.Browser.Value) {
|
||||
if (ConfigData.Browser.Value)
|
||||
{
|
||||
|
||||
// Clean headers
|
||||
emulatedBrowserHeaders.Clear();
|
||||
|
@ -149,7 +150,8 @@ namespace Jackett.Indexers
|
|||
};
|
||||
|
||||
// Do the login
|
||||
var request = new Utils.Clients.WebRequest(){
|
||||
var request = new Utils.Clients.WebRequest()
|
||||
{
|
||||
PostData = pairs,
|
||||
Referer = LoginUrl,
|
||||
Type = RequestType.POST,
|
||||
|
@ -197,7 +199,7 @@ namespace Jackett.Indexers
|
|||
int pageLinkCount = 0;
|
||||
|
||||
// Check cache first so we don't query the server (if search term used or not in dev mode)
|
||||
if(!DevMode && !string.IsNullOrEmpty(searchTerm))
|
||||
if (!DevMode && !string.IsNullOrEmpty(searchTerm))
|
||||
{
|
||||
lock (cache)
|
||||
{
|
||||
|
@ -230,14 +232,16 @@ namespace Jackett.Indexers
|
|||
Boolean pagination = (fDom[".linkbox > a"].Length != 0);
|
||||
|
||||
// If pagination available
|
||||
if (pagination) {
|
||||
if (pagination)
|
||||
{
|
||||
// Calculate numbers of pages available for this search query (Based on number results and number of torrents on first page)
|
||||
pageLinkCount = ParseUtil.CoerceInt(Regex.Match(fDom[".linkbox > a"].Last().Attr("href").ToString(), @"\d+").Value);
|
||||
|
||||
// Calculate average number of results (based on torrents rows lenght on first page)
|
||||
nbResults = firstPageRows.Count() * pageLinkCount;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// Check if we have a minimum of one result
|
||||
if (firstPageRows.Length >= 1)
|
||||
{
|
||||
|
@ -528,13 +532,13 @@ namespace Jackett.Indexers
|
|||
private void cleanCacheStorage(Boolean force = false)
|
||||
{
|
||||
// Check cleaning method
|
||||
if(force)
|
||||
if (force)
|
||||
{
|
||||
// Deleting Provider Storage folder and all files recursively
|
||||
output("\nDeleting Provider Storage folder and all files recursively ...");
|
||||
|
||||
|
||||
// Check if directory exist
|
||||
if(System.IO.Directory.Exists(directory))
|
||||
if (System.IO.Directory.Exists(directory))
|
||||
{
|
||||
// Delete storage directory of provider
|
||||
System.IO.Directory.Delete(directory, true);
|
||||
|
@ -555,17 +559,20 @@ namespace Jackett.Indexers
|
|||
.Select(f => new System.IO.FileInfo(f))
|
||||
.Where(f => f.LastAccessTime < DateTime.Now.AddMilliseconds(-Convert.ToInt32(ConfigData.HardDriveCacheKeepTime.Value)))
|
||||
.ToList()
|
||||
.ForEach(f => {
|
||||
.ForEach(f =>
|
||||
{
|
||||
output("Deleting cached file << " + f.Name + " >> ... done.");
|
||||
f.Delete();
|
||||
i++;
|
||||
});
|
||||
});
|
||||
|
||||
// Inform on what was cleaned during process
|
||||
if(i > 0) {
|
||||
if (i > 0)
|
||||
{
|
||||
output("-> Deleted " + i + " cached files during cleaning.");
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
output("-> Nothing deleted during cleaning.");
|
||||
}
|
||||
}
|
||||
|
@ -577,7 +584,7 @@ namespace Jackett.Indexers
|
|||
private void latencyNow()
|
||||
{
|
||||
// Need latency ?
|
||||
if(Latency)
|
||||
if (Latency)
|
||||
{
|
||||
// Generate a random value in our range
|
||||
var random = new Random(DateTime.Now.Millisecond);
|
||||
|
@ -696,7 +703,7 @@ namespace Jackett.Indexers
|
|||
private void output(string message, string level = "debug")
|
||||
{
|
||||
// Check if we are in dev mode
|
||||
if(DevMode)
|
||||
if (DevMode)
|
||||
{
|
||||
// Output message to console
|
||||
Console.WriteLine(message);
|
||||
|
|
|
@ -18,7 +18,7 @@ using Jackett.Models.IndexerConfig;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public abstract class AvistazTracker : BaseIndexer
|
||||
public abstract class AvistazTracker : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "auth/login"; } }
|
||||
private string SearchUrl { get { return SiteLink + "torrents?in=1&type={0}&search={1}"; } }
|
||||
|
@ -29,12 +29,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public AvistazTracker(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService, string name, string desc, string link)
|
||||
public AvistazTracker(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService, string name, string desc, string link)
|
||||
: base(name: name,
|
||||
description: desc,
|
||||
link: link,
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: indexerManager,
|
||||
configService: configService,
|
||||
client: webClient,
|
||||
logger: logger,
|
||||
p: protectionService,
|
||||
|
|
|
@ -17,7 +17,7 @@ using System.Web;
|
|||
|
||||
namespace Jackett.Indexers.Abstract
|
||||
{
|
||||
public abstract class GazelleTracker : BaseIndexer
|
||||
public abstract class GazelleTracker : BaseWebIndexer
|
||||
{
|
||||
protected string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
protected string APIUrl { get { return SiteLink + "ajax.php"; } }
|
||||
|
@ -30,12 +30,12 @@ namespace Jackett.Indexers.Abstract
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public GazelleTracker(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService, string name, string desc, string link)
|
||||
public GazelleTracker(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService, string name, string desc, string link)
|
||||
: base(name: name,
|
||||
description: desc,
|
||||
link: link,
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: indexerManager,
|
||||
configService: configService,
|
||||
client: webClient,
|
||||
logger: logger,
|
||||
p: protectionService,
|
||||
|
|
|
@ -19,19 +19,19 @@ using System.Collections.Specialized;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class AlphaRatio : BaseIndexer
|
||||
public class AlphaRatio : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "ajax.php?action=browse&order_by=time&order_way=desc&"; } }
|
||||
private string DownloadUrl { get { return SiteLink + "torrents.php?action=download&id="; } }
|
||||
private string GuidUrl { get { return SiteLink + "torrents.php?torrentid="; } }
|
||||
|
||||
public AlphaRatio(IIndexerManagerService i, IWebClient w, Logger l, IProtectionService ps)
|
||||
public AlphaRatio(IIndexerConfigurationService configService, IWebClient w, Logger l, IProtectionService ps)
|
||||
: base(name: "AlphaRatio",
|
||||
description: "Legendary",
|
||||
link: "https://alpharatio.cc/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -16,7 +16,7 @@ using System.Linq;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class Andraste : BaseIndexer
|
||||
public class Andraste : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
string BrowseUrl { get { return SiteLink + "browse.php"; } }
|
||||
|
@ -27,12 +27,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Andraste(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public Andraste(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "Andraste",
|
||||
description: "A German general tracker.",
|
||||
link: "https://andraste.io/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -22,7 +22,7 @@ using System.Web;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class AnimeBytes : BaseIndexer
|
||||
public class AnimeBytes : BaseCachingWebIndexer
|
||||
{
|
||||
enum SearchType
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ namespace Jackett.Indexers
|
|||
private string SearchUrl { get { return SiteLink + "torrents.php?"; } }
|
||||
private string MusicSearchUrl { get { return SiteLink + "torrents2.php?"; } }
|
||||
public bool AllowRaws { get { return configData.IncludeRaw.Value; } }
|
||||
public bool InsertSeason { get { return configData.InsertSeason!=null && configData.InsertSeason.Value; } }
|
||||
public bool InsertSeason { get { return configData.InsertSeason != null && configData.InsertSeason.Value; } }
|
||||
|
||||
new ConfigurationDataAnimeBytes configData
|
||||
{
|
||||
|
@ -42,11 +42,11 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public AnimeBytes(IIndexerManagerService i, IWebClient client, Logger l, IProtectionService ps)
|
||||
public AnimeBytes(IIndexerConfigurationService configService, IWebClient client, Logger l, IProtectionService ps)
|
||||
: base(name: "AnimeBytes",
|
||||
link: "https://animebytes.tv/",
|
||||
description: "Powered by Tentacles",
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: client,
|
||||
caps: new TorznabCapabilities(TorznabCatType.TVAnime,
|
||||
TorznabCatType.Movies,
|
||||
|
@ -67,7 +67,7 @@ namespace Jackett.Indexers
|
|||
}
|
||||
|
||||
|
||||
public override IEnumerable<ReleaseInfo> FilterResults(TorznabQuery query, IEnumerable<ReleaseInfo> input)
|
||||
protected override IEnumerable<ReleaseInfo> FilterResults(TorznabQuery query, IEnumerable<ReleaseInfo> input)
|
||||
{
|
||||
// Prevent filtering
|
||||
return input;
|
||||
|
@ -128,21 +128,6 @@ namespace Jackett.Indexers
|
|||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
}
|
||||
|
||||
// Override to load legacy config format
|
||||
public override void LoadFromSavedConfiguration(JToken jsonConfig)
|
||||
{
|
||||
if (jsonConfig is JObject)
|
||||
{
|
||||
configData.CookieHeader.Value = jsonConfig.Value<string>("cookies");
|
||||
configData.IncludeRaw.Value = jsonConfig.Value<bool>("raws");
|
||||
IsConfigured = true;
|
||||
SaveConfig();
|
||||
return;
|
||||
}
|
||||
|
||||
base.LoadFromSavedConfiguration(jsonConfig);
|
||||
}
|
||||
|
||||
private string StripEpisodeNumber(string term)
|
||||
{
|
||||
// Tracer does not support searching with episode number so strip it if we have one
|
||||
|
@ -155,7 +140,7 @@ namespace Jackett.Indexers
|
|||
{
|
||||
// The result list
|
||||
var releases = new List<ReleaseInfo>();
|
||||
|
||||
|
||||
if (ContainsMusicCategories(query.Categories))
|
||||
{
|
||||
foreach (var result in await GetResults(SearchType.Audio, query.SanitizedSearchTerm))
|
||||
|
@ -210,7 +195,7 @@ namespace Jackett.Indexers
|
|||
if (cachedResult != null)
|
||||
return cachedResult.Results.Select(s => (ReleaseInfo)s.Clone()).ToArray();
|
||||
}
|
||||
|
||||
|
||||
// Get the content from the tracker
|
||||
var response = await RequestStringWithCookiesAndRetry(queryUrl);
|
||||
if (response.IsRedirect)
|
||||
|
@ -302,7 +287,7 @@ namespace Jackett.Indexers
|
|||
releaseInfo = releaseInfo.Replace("Season ", "S");
|
||||
releaseInfo = releaseInfo.Trim();
|
||||
int test = 0;
|
||||
if (InsertSeason && int.TryParse(releaseInfo, out test) && releaseInfo.Length<=3)
|
||||
if (InsertSeason && int.TryParse(releaseInfo, out test) && releaseInfo.Length <= 3)
|
||||
{
|
||||
releaseInfo = "E0" + releaseInfo;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ using System.Globalization;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class AnimeTorrents : BaseIndexer
|
||||
public class AnimeTorrents : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "ajax/torrents_data.php"; } }
|
||||
|
@ -32,12 +32,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public AnimeTorrents(IIndexerManagerService i, HttpWebClient c, Logger l, IProtectionService ps)
|
||||
public AnimeTorrents(IIndexerConfigurationService configService, HttpWebClient c, Logger l, IProtectionService ps)
|
||||
: base(name: "AnimeTorrents",
|
||||
description: "Definitive source for anime and manga",
|
||||
link: "https://animetorrents.me/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: c, // Forced HTTP client for custom headers
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -18,7 +18,7 @@ using Jackett.Utils.Clients;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
class ArcheTorrent : BaseIndexer
|
||||
class ArcheTorrent : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "account-login.php"; } }
|
||||
string BrowseUrl { get { return SiteLink + "torrents-search.php"; } }
|
||||
|
@ -30,11 +30,11 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public ArcheTorrent(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
public ArcheTorrent(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
: base(name: "Arche Torrent",
|
||||
description: "French Torrent Tracker",
|
||||
link: "https://www.archetorrent.com/",
|
||||
manager: indexerManager,
|
||||
configService: configService,
|
||||
logger: logger,
|
||||
p: protectionService,
|
||||
client: webClient,
|
||||
|
|
|
@ -20,11 +20,11 @@ namespace Jackett.Indexers
|
|||
{
|
||||
public class Avistaz : AvistazTracker
|
||||
{
|
||||
public Avistaz(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
public Avistaz(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
: base(name: "Avistaz",
|
||||
desc: "Aka AsiaTorrents",
|
||||
link: "https://avistaz.to/",
|
||||
indexerManager: indexerManager,
|
||||
configService: configService,
|
||||
logger: logger,
|
||||
protectionService: protectionService,
|
||||
webClient: webClient
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Jackett.Indexers
|
|||
{
|
||||
// To comply with the rules for this tracker, only the acronym is used and no publicly displayed URLs to the site.
|
||||
|
||||
public class BB : BaseIndexer
|
||||
public class BB : BaseWebIndexer
|
||||
{
|
||||
private string BaseUrl { get { return StringUtil.FromBase64("aHR0cHM6Ly9iYWNvbmJpdHMub3JnLw=="); } }
|
||||
private Uri BaseUri { get { return new Uri(BaseUrl); } }
|
||||
|
@ -33,12 +33,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public BB(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public BB(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "bB",
|
||||
description: "bB",
|
||||
link: "https://baconbits.org/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -17,7 +17,7 @@ using System.Text.RegularExpressions;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class BJShare : BaseIndexer
|
||||
public class BJShare : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
string BrowseUrl { get { return SiteLink + "torrents.php"; } }
|
||||
|
@ -29,12 +29,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public BJShare(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public BJShare(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "BJ-Share",
|
||||
description: "A brazilian tracker.",
|
||||
link: "https://bj-share.me/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -17,7 +17,7 @@ using Jackett.Models.IndexerConfig;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class BakaBT : BaseIndexer
|
||||
public class BakaBT : BaseWebIndexer
|
||||
{
|
||||
public string SearchUrl { get { return SiteLink + "browse.php?only=0&incomplete=1&lossless=1&hd=1&multiaudio=1&bonus=1&reorder=1&q="; } }
|
||||
public string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
|
@ -29,12 +29,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public BakaBT(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public BakaBT(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "BakaBT",
|
||||
description: "Anime Comunity",
|
||||
link: "https://bakabt.me/",
|
||||
caps: new TorznabCapabilities(TorznabCatType.TVAnime),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -10,7 +10,6 @@ using Jackett.Services;
|
|||
using Jackett.Utils;
|
||||
using Jackett.Utils.Clients;
|
||||
using AutoMapper;
|
||||
using System.Threading;
|
||||
using Jackett.Models.IndexerConfig;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
@ -18,25 +17,26 @@ namespace Jackett.Indexers
|
|||
{
|
||||
public abstract class BaseIndexer : IIndexer
|
||||
{
|
||||
public static string GetIndexerID(Type type)
|
||||
{
|
||||
return type.Name.ToLowerInvariant().StripNonAlphaNumeric();
|
||||
}
|
||||
|
||||
public string SiteLink { get; protected set; }
|
||||
public string DefaultSiteLink { get; protected set; }
|
||||
public string[] AlternativeSiteLinks { get; protected set; } = new string[] { };
|
||||
public string DisplayDescription { get; protected set; }
|
||||
public string DisplayName { get; protected set; }
|
||||
public string Language { get; protected set; }
|
||||
public Encoding Encoding { get; protected set; }
|
||||
public string Type { get; protected set; }
|
||||
public virtual string ID { get { return GetIndexerID (GetType ()); } }
|
||||
public virtual string ID { get { return GetIndexerID(GetType()); } }
|
||||
|
||||
public bool IsConfigured { get; protected set; }
|
||||
public TorznabCapabilities TorznabCaps { get; protected set; }
|
||||
public virtual bool IsConfigured { get; protected set; }
|
||||
protected Logger logger;
|
||||
protected IIndexerManagerService indexerService;
|
||||
protected static List<CachedQueryResult> cache = new List<CachedQueryResult>();
|
||||
protected static readonly TimeSpan cacheTime = new TimeSpan(0, 9, 0);
|
||||
protected IWebClient webclient;
|
||||
protected IIndexerConfigurationService configurationService;
|
||||
protected IProtectionService protectionService;
|
||||
protected readonly string downloadUrlBase = "";
|
||||
|
||||
protected ConfigurationData configData;
|
||||
|
||||
protected string CookieHeader
|
||||
{
|
||||
|
@ -56,14 +56,15 @@ namespace Jackett.Indexers
|
|||
}
|
||||
}
|
||||
|
||||
protected ConfigurationData configData;
|
||||
|
||||
private List<CategoryMapping> categoryMapping = new List<CategoryMapping>();
|
||||
public abstract TorznabCapabilities TorznabCaps { get; protected set; }
|
||||
|
||||
// standard constructor used by most indexers
|
||||
public BaseIndexer(string name, string link, string description, IIndexerManagerService manager, IWebClient client, Logger logger, ConfigurationData configData, IProtectionService p, TorznabCapabilities caps = null, string downloadBase = null)
|
||||
: this(manager, client, logger, p)
|
||||
public BaseIndexer(string name, string link, string description, IIndexerConfigurationService configService, Logger logger, ConfigurationData configData, IProtectionService p)
|
||||
{
|
||||
this.logger = logger;
|
||||
configurationService = configService;
|
||||
protectionService = p;
|
||||
|
||||
if (!link.EndsWith("/", StringComparison.Ordinal))
|
||||
throw new Exception("Site link must end with a slash.");
|
||||
|
||||
|
@ -71,111 +72,9 @@ namespace Jackett.Indexers
|
|||
DisplayDescription = description;
|
||||
SiteLink = link;
|
||||
DefaultSiteLink = link;
|
||||
this.downloadUrlBase = downloadBase;
|
||||
this.configData = configData;
|
||||
LoadValuesFromJson(null);
|
||||
|
||||
if (caps == null)
|
||||
caps = TorznabUtil.CreateDefaultTorznabTVCaps();
|
||||
TorznabCaps = caps;
|
||||
|
||||
}
|
||||
|
||||
// minimal constructor used by e.g. cardigann generic indexer
|
||||
public BaseIndexer(IIndexerManagerService manager, IWebClient client, Logger logger, IProtectionService p)
|
||||
{
|
||||
this.logger = logger;
|
||||
indexerService = manager;
|
||||
webclient = client;
|
||||
protectionService = p;
|
||||
}
|
||||
|
||||
public IEnumerable<ReleaseInfo> CleanLinks(IEnumerable<ReleaseInfo> releases)
|
||||
{
|
||||
if (string.IsNullOrEmpty(downloadUrlBase))
|
||||
return releases;
|
||||
foreach (var release in releases)
|
||||
{
|
||||
if (release.Link.ToString().StartsWith(downloadUrlBase, StringComparison.Ordinal))
|
||||
{
|
||||
release.Link = new Uri(release.Link.ToString().Substring(downloadUrlBase.Length), UriKind.Relative);
|
||||
}
|
||||
}
|
||||
|
||||
return releases;
|
||||
}
|
||||
|
||||
public virtual Uri UncleanLink(Uri link)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(downloadUrlBase))
|
||||
{
|
||||
return link;
|
||||
}
|
||||
|
||||
if (link.ToString().StartsWith(downloadUrlBase, StringComparison.Ordinal))
|
||||
{
|
||||
return link;
|
||||
}
|
||||
|
||||
return new Uri(downloadUrlBase + link.ToString(), UriKind.RelativeOrAbsolute);
|
||||
}
|
||||
|
||||
protected ICollection<int> MapTrackerCatToNewznab(string input)
|
||||
{
|
||||
var cats = new List<int>();
|
||||
if (null != input)
|
||||
{
|
||||
var mapping = categoryMapping.Where(m => m.TrackerCategory != null && m.TrackerCategory.ToLowerInvariant() == input.ToLowerInvariant()).FirstOrDefault();
|
||||
if (mapping != null)
|
||||
{
|
||||
cats.Add(mapping.NewzNabCategory);
|
||||
}
|
||||
|
||||
// 1:1 category mapping
|
||||
try
|
||||
{
|
||||
var trackerCategoryInt = int.Parse(input);
|
||||
cats.Add(trackerCategoryInt + 100000);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
// input is not an integer, continue
|
||||
}
|
||||
}
|
||||
return cats;
|
||||
}
|
||||
|
||||
protected ICollection<int> MapTrackerCatDescToNewznab(string input)
|
||||
{
|
||||
var cats = new List<int>();
|
||||
if (null != input)
|
||||
{
|
||||
var mapping = categoryMapping.Where(m => m.TrackerCategoryDesc != null && m.TrackerCategoryDesc.ToLowerInvariant() == input.ToLowerInvariant()).FirstOrDefault();
|
||||
if (mapping != null)
|
||||
{
|
||||
cats.Add(mapping.NewzNabCategory);
|
||||
|
||||
if (mapping.TrackerCategory != null)
|
||||
{
|
||||
// 1:1 category mapping
|
||||
try
|
||||
{
|
||||
var trackerCategoryInt = int.Parse(mapping.TrackerCategory);
|
||||
cats.Add(trackerCategoryInt + 100000);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
// mapping.TrackerCategory is not an integer, continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return cats;
|
||||
}
|
||||
|
||||
public static string GetIndexerID(Type type)
|
||||
{
|
||||
return StringUtil.StripNonAlphaNumeric(type.Name.ToLowerInvariant());
|
||||
if (configData != null)
|
||||
LoadValuesFromJson(null);
|
||||
}
|
||||
|
||||
public virtual Task<ConfigurationData> GetConfigurationForSetup()
|
||||
|
@ -191,109 +90,9 @@ namespace Jackett.Indexers
|
|||
|
||||
public virtual void SaveConfig()
|
||||
{
|
||||
indexerService.SaveConfig(this as IIndexer, configData.ToJson(protectionService, forDisplay: false));
|
||||
configurationService.Save(this as IIndexer, configData.ToJson(protectionService, forDisplay: false));
|
||||
}
|
||||
|
||||
protected void OnParseError(string results, Exception ex)
|
||||
{
|
||||
var fileName = string.Format("Error on {0} for {1}.txt", DateTime.Now.ToString("yyyyMMddHHmmss"), DisplayName);
|
||||
var spacing = string.Join("", Enumerable.Repeat(Environment.NewLine, 5));
|
||||
var fileContents = string.Format("{0}{1}{2}", ex, spacing, results);
|
||||
logger.Error(fileName + fileContents);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
protected void CleanCache()
|
||||
{
|
||||
foreach (var expired in cache.Where(i => DateTime.Now - i.Created > cacheTime).ToList())
|
||||
{
|
||||
cache.Remove(expired);
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task FollowIfRedirect(WebClientStringResult response, string referrer = null, string overrideRedirectUrl = null, string overrideCookies = null, bool accumulateCookies = false)
|
||||
{
|
||||
var byteResult = new WebClientByteResult();
|
||||
// Map to byte
|
||||
Mapper.Map(response, byteResult);
|
||||
await FollowIfRedirect(byteResult, referrer, overrideRedirectUrl, overrideCookies, accumulateCookies);
|
||||
// Map to string
|
||||
Mapper.Map(byteResult, response);
|
||||
}
|
||||
|
||||
protected async Task FollowIfRedirect(WebClientByteResult response, string referrer = null, string overrideRedirectUrl = null, string overrideCookies = null, bool accumulateCookies = false)
|
||||
{
|
||||
// Follow up to 5 redirects
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (!response.IsRedirect)
|
||||
break;
|
||||
await DoFollowIfRedirect(response, referrer, overrideRedirectUrl, overrideCookies, accumulateCookies);
|
||||
if (accumulateCookies)
|
||||
{
|
||||
CookieHeader = ResolveCookies((CookieHeader != null && CookieHeader != ""? CookieHeader + " " : "") + (overrideCookies != null && overrideCookies != "" ? overrideCookies + " " : "") + response.Cookies);
|
||||
overrideCookies = response.Cookies = CookieHeader;
|
||||
}
|
||||
if (overrideCookies != null && response.Cookies == null)
|
||||
{
|
||||
response.Cookies = overrideCookies;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String ResolveCookies(String incomingCookies = "")
|
||||
{
|
||||
var redirRequestCookies = (CookieHeader != null && CookieHeader != "" ? CookieHeader + " " : "") + incomingCookies;
|
||||
System.Text.RegularExpressions.Regex expression = new System.Text.RegularExpressions.Regex(@"([^\\,;\s]+)=([^=\\,;\s]*)");
|
||||
Dictionary<string, string> cookieDIctionary = new Dictionary<string, string>();
|
||||
var matches = expression.Match(redirRequestCookies);
|
||||
while (matches.Success)
|
||||
{
|
||||
if (matches.Groups.Count > 2) cookieDIctionary[matches.Groups[1].Value] = matches.Groups[2].Value;
|
||||
matches = matches.NextMatch();
|
||||
}
|
||||
return string.Join("; ", cookieDIctionary.Select(kv => kv.Key.ToString() + "=" + kv.Value.ToString()).ToArray());
|
||||
|
||||
}
|
||||
|
||||
// Update CookieHeader with new cookies and save the config if something changed (e.g. a new CloudFlare clearance cookie was issued)
|
||||
protected void UpdateCookieHeader(string newCookies, string cookieOverride = null)
|
||||
{
|
||||
string newCookieHeader = ResolveCookies((cookieOverride != null && cookieOverride != "" ? cookieOverride + " " : "") + newCookies);
|
||||
if (CookieHeader != newCookieHeader)
|
||||
{
|
||||
logger.Debug(string.Format("updating Cookies {0} => {1}", CookieHeader, newCookieHeader));
|
||||
CookieHeader = newCookieHeader;
|
||||
if (IsConfigured)
|
||||
SaveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DoFollowIfRedirect(WebClientByteResult incomingResponse, string referrer = null, string overrideRedirectUrl = null, string overrideCookies = null, bool accumulateCookies = false)
|
||||
{
|
||||
if (incomingResponse.IsRedirect)
|
||||
{
|
||||
var redirRequestCookies = "";
|
||||
if (accumulateCookies)
|
||||
{
|
||||
redirRequestCookies = ResolveCookies((CookieHeader != "" ? CookieHeader + " " : "") + (overrideCookies != null ? overrideCookies : ""));
|
||||
} else
|
||||
{
|
||||
redirRequestCookies = (overrideCookies != null ? overrideCookies : "");
|
||||
}
|
||||
// Do redirect
|
||||
var redirectedResponse = await webclient.GetBytes(new WebRequest()
|
||||
{
|
||||
Url = overrideRedirectUrl ?? incomingResponse.RedirectingTo,
|
||||
Referer = referrer,
|
||||
Cookies = redirRequestCookies,
|
||||
Encoding = Encoding
|
||||
});
|
||||
Mapper.Map(redirectedResponse, incomingResponse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void LoadLegacyCookieConfig(JToken jsonConfig)
|
||||
{
|
||||
string legacyCookieHeader = (string)jsonConfig["cookie_header"];
|
||||
|
@ -346,7 +145,7 @@ namespace Jackett.Indexers
|
|||
SiteLink = configData.SiteLink.Value;
|
||||
}
|
||||
|
||||
public virtual void LoadFromSavedConfiguration(JToken jsonConfig)
|
||||
public void LoadFromSavedConfiguration(JToken jsonConfig)
|
||||
{
|
||||
if (jsonConfig is JArray)
|
||||
{
|
||||
|
@ -362,8 +161,100 @@ namespace Jackett.Indexers
|
|||
}
|
||||
}
|
||||
|
||||
public async virtual Task<byte[]> Download(Uri link) {
|
||||
return await Download(link, RequestType.GET);
|
||||
protected async Task ConfigureIfOK(string cookies, bool isLoggedin, Func<Task> onError)
|
||||
{
|
||||
if (isLoggedin)
|
||||
{
|
||||
CookieHeader = cookies;
|
||||
IsConfigured = true;
|
||||
SaveConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
await onError();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual IEnumerable<ReleaseInfo> FilterResults(TorznabQuery query, IEnumerable<ReleaseInfo> results)
|
||||
{
|
||||
if (query.Categories.Length == 0)
|
||||
return results;
|
||||
|
||||
var filteredResults = results.Where(result =>
|
||||
{
|
||||
return result.Category.IsEmptyOrNull() || query.Categories.Intersect(result.Category).Any() || TorznabCatType.QueryContainsParentCategory(query.Categories, result.Category);
|
||||
});
|
||||
|
||||
return filteredResults;
|
||||
}
|
||||
|
||||
public bool CanHandleQuery(TorznabQuery query)
|
||||
{
|
||||
if (query == null)
|
||||
return false;
|
||||
var caps = TorznabCaps;
|
||||
if (!caps.SearchAvailable && query.IsSearch)
|
||||
return false;
|
||||
if (!caps.TVSearchAvailable && query.IsTVSearch)
|
||||
return false;
|
||||
if (!caps.MovieSearchAvailable && query.IsMovieSearch)
|
||||
return false;
|
||||
if (!caps.SupportsTVRageSearch && query.IsTVRageSearch)
|
||||
return false;
|
||||
if (!caps.SupportsImdbSearch && query.IsImdbQuery)
|
||||
return false;
|
||||
|
||||
if (query.HasSpecifiedCategories)
|
||||
if (!caps.SupportsCategories(query.Categories))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Unconfigure()
|
||||
{
|
||||
IsConfigured = false;
|
||||
}
|
||||
|
||||
public abstract Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson);
|
||||
|
||||
public virtual async Task<IEnumerable<ReleaseInfo>> ResultsForQuery(TorznabQuery query)
|
||||
{
|
||||
var results = await PerformQuery(query);
|
||||
results = FilterResults(query, results);
|
||||
foreach (var result in results)
|
||||
{
|
||||
result.Origin = this;
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
protected abstract Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query);
|
||||
}
|
||||
|
||||
public abstract class BaseWebIndexer : BaseIndexer, IWebIndexer
|
||||
{
|
||||
protected BaseWebIndexer(string name, string link, string description, IIndexerConfigurationService configService, IWebClient client, Logger logger, ConfigurationData configData, IProtectionService p, TorznabCapabilities caps = null, string downloadBase = null)
|
||||
: base(name, link, description, configService, logger, configData, p)
|
||||
{
|
||||
this.webclient = client;
|
||||
this.downloadUrlBase = downloadBase;
|
||||
|
||||
if (caps == null)
|
||||
caps = TorznabUtil.CreateDefaultTorznabTVCaps();
|
||||
TorznabCaps = caps;
|
||||
}
|
||||
|
||||
// minimal constructor used by e.g. cardigann generic indexer
|
||||
protected BaseWebIndexer(IIndexerConfigurationService configService, IWebClient client, Logger logger, IProtectionService p)
|
||||
: base("", "/", "", configService, logger, null, p)
|
||||
{
|
||||
this.webclient = client;
|
||||
}
|
||||
|
||||
public async virtual Task<byte[]> Download(Uri link)
|
||||
{
|
||||
var uncleanLink = UncleanLink(link);
|
||||
return await Download(uncleanLink, RequestType.GET);
|
||||
}
|
||||
|
||||
protected async Task<byte[]> Download(Uri link, RequestType method)
|
||||
|
@ -379,7 +270,7 @@ namespace Jackett.Indexers
|
|||
logger.Error("Failed download cookies: " + this.CookieHeader);
|
||||
if (response.Content != null)
|
||||
logger.Error("Failed download response:\n" + Encoding.UTF8.GetString(response.Content));
|
||||
throw new Exception($"Remote server returned {response.Status.ToString()}" + (response.IsRedirect ? " => "+response.RedirectingTo : ""));
|
||||
throw new Exception($"Remote server returned {response.Status.ToString()}" + (response.IsRedirect ? " => " + response.RedirectingTo : ""));
|
||||
}
|
||||
|
||||
return response.Content;
|
||||
|
@ -530,32 +421,90 @@ namespace Jackett.Indexers
|
|||
{
|
||||
response.Cookies = ResolveCookies(firstCallCookies + (accumulateCookies ? " " + response.Cookies : ""));
|
||||
}
|
||||
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
protected async Task ConfigureIfOK(string cookies, bool isLoggedin, Func<Task> onError)
|
||||
protected async Task FollowIfRedirect(WebClientStringResult response, string referrer = null, string overrideRedirectUrl = null, string overrideCookies = null, bool accumulateCookies = false)
|
||||
{
|
||||
if (isLoggedin)
|
||||
var byteResult = new WebClientByteResult();
|
||||
// Map to byte
|
||||
Mapper.Map(response, byteResult);
|
||||
await FollowIfRedirect(byteResult, referrer, overrideRedirectUrl, overrideCookies, accumulateCookies);
|
||||
// Map to string
|
||||
Mapper.Map(byteResult, response);
|
||||
}
|
||||
|
||||
protected async Task FollowIfRedirect(WebClientByteResult response, string referrer = null, string overrideRedirectUrl = null, string overrideCookies = null, bool accumulateCookies = false)
|
||||
{
|
||||
// Follow up to 5 redirects
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
CookieHeader = cookies;
|
||||
IsConfigured = true;
|
||||
SaveConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
await onError();
|
||||
if (!response.IsRedirect)
|
||||
break;
|
||||
await DoFollowIfRedirect(response, referrer, overrideRedirectUrl, overrideCookies, accumulateCookies);
|
||||
if (accumulateCookies)
|
||||
{
|
||||
CookieHeader = ResolveCookies((CookieHeader != null && CookieHeader != "" ? CookieHeader + " " : "") + (overrideCookies != null && overrideCookies != "" ? overrideCookies + " " : "") + response.Cookies);
|
||||
overrideCookies = response.Cookies = CookieHeader;
|
||||
}
|
||||
if (overrideCookies != null && response.Cookies == null)
|
||||
{
|
||||
response.Cookies = overrideCookies;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual IEnumerable<ReleaseInfo> FilterResults(TorznabQuery query, IEnumerable<ReleaseInfo> results)
|
||||
private String ResolveCookies(String incomingCookies = "")
|
||||
{
|
||||
foreach (var result in results)
|
||||
var redirRequestCookies = (CookieHeader != null && CookieHeader != "" ? CookieHeader + " " : "") + incomingCookies;
|
||||
System.Text.RegularExpressions.Regex expression = new System.Text.RegularExpressions.Regex(@"([^\\,;\s]+)=([^=\\,;\s]*)");
|
||||
Dictionary<string, string> cookieDIctionary = new Dictionary<string, string>();
|
||||
var matches = expression.Match(redirRequestCookies);
|
||||
while (matches.Success)
|
||||
{
|
||||
if (query.Categories.Length == 0 || result.Category == null || result.Category.Count() == 0 || query.Categories.Intersect(result.Category).Any() || TorznabCatType.QueryContainsParentCategory(query.Categories, result.Category))
|
||||
if (matches.Groups.Count > 2) cookieDIctionary[matches.Groups[1].Value] = matches.Groups[2].Value;
|
||||
matches = matches.NextMatch();
|
||||
}
|
||||
return string.Join("; ", cookieDIctionary.Select(kv => kv.Key.ToString() + "=" + kv.Value.ToString()).ToArray());
|
||||
|
||||
}
|
||||
|
||||
// Update CookieHeader with new cookies and save the config if something changed (e.g. a new CloudFlare clearance cookie was issued)
|
||||
protected void UpdateCookieHeader(string newCookies, string cookieOverride = null)
|
||||
{
|
||||
string newCookieHeader = ResolveCookies((cookieOverride != null && cookieOverride != "" ? cookieOverride + " " : "") + newCookies);
|
||||
if (CookieHeader != newCookieHeader)
|
||||
{
|
||||
logger.Debug(string.Format("updating Cookies {0} => {1}", CookieHeader, newCookieHeader));
|
||||
CookieHeader = newCookieHeader;
|
||||
if (IsConfigured)
|
||||
SaveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DoFollowIfRedirect(WebClientByteResult incomingResponse, string referrer = null, string overrideRedirectUrl = null, string overrideCookies = null, bool accumulateCookies = false)
|
||||
{
|
||||
if (incomingResponse.IsRedirect)
|
||||
{
|
||||
var redirRequestCookies = "";
|
||||
if (accumulateCookies)
|
||||
{
|
||||
yield return result;
|
||||
redirRequestCookies = ResolveCookies((CookieHeader != "" ? CookieHeader + " " : "") + (overrideCookies != null ? overrideCookies : ""));
|
||||
}
|
||||
else
|
||||
{
|
||||
redirRequestCookies = (overrideCookies != null ? overrideCookies : "");
|
||||
}
|
||||
// Do redirect
|
||||
var redirectedResponse = await webclient.GetBytes(new WebRequest()
|
||||
{
|
||||
Url = overrideRedirectUrl ?? incomingResponse.RedirectingTo,
|
||||
Referer = referrer,
|
||||
Cookies = redirRequestCookies,
|
||||
Encoding = Encoding
|
||||
});
|
||||
Mapper.Map(redirectedResponse, incomingResponse);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -641,40 +590,130 @@ namespace Jackett.Indexers
|
|||
return result.Distinct().ToList();
|
||||
}
|
||||
|
||||
public bool CanHandleQuery(TorznabQuery query)
|
||||
protected ICollection<int> MapTrackerCatToNewznab(string input)
|
||||
{
|
||||
if (query == null)
|
||||
return false;
|
||||
var caps = TorznabCaps;
|
||||
if (!caps.SearchAvailable && query.IsSearch)
|
||||
return false;
|
||||
if (!caps.TVSearchAvailable && query.IsTVSearch)
|
||||
return false;
|
||||
if (!caps.MovieSearchAvailable && query.IsMovieSearch)
|
||||
return false;
|
||||
if (!caps.SupportsTVRageSearch && query.IsTVRageSearch)
|
||||
return false;
|
||||
if (!caps.SupportsImdbSearch && query.IsImdbQuery)
|
||||
return false;
|
||||
var cats = new List<int>();
|
||||
if (null != input)
|
||||
{
|
||||
var mapping = categoryMapping.Where(m => m.TrackerCategory != null && m.TrackerCategory.ToLowerInvariant() == input.ToLowerInvariant()).FirstOrDefault();
|
||||
if (mapping != null)
|
||||
{
|
||||
cats.Add(mapping.NewzNabCategory);
|
||||
}
|
||||
|
||||
if (query.HasSpecifiedCategories)
|
||||
if (!caps.SupportsCategories(query.Categories))
|
||||
return false;
|
||||
return true;
|
||||
// 1:1 category mapping
|
||||
try
|
||||
{
|
||||
var trackerCategoryInt = int.Parse(input);
|
||||
cats.Add(trackerCategoryInt + 100000);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
// input is not an integer, continue
|
||||
}
|
||||
}
|
||||
return cats;
|
||||
}
|
||||
|
||||
public abstract Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson);
|
||||
|
||||
public virtual async Task<IEnumerable<ReleaseInfo>> ResultsForQuery(TorznabQuery query)
|
||||
protected ICollection<int> MapTrackerCatDescToNewznab(string input)
|
||||
{
|
||||
var results = await PerformQuery(query);
|
||||
foreach (var result in results)
|
||||
var cats = new List<int>();
|
||||
if (null != input)
|
||||
{
|
||||
result.Origin = this;
|
||||
var mapping = categoryMapping.Where(m => m.TrackerCategoryDesc != null && m.TrackerCategoryDesc.ToLowerInvariant() == input.ToLowerInvariant()).FirstOrDefault();
|
||||
if (mapping != null)
|
||||
{
|
||||
cats.Add(mapping.NewzNabCategory);
|
||||
|
||||
if (mapping.TrackerCategory != null)
|
||||
{
|
||||
// 1:1 category mapping
|
||||
try
|
||||
{
|
||||
var trackerCategoryInt = int.Parse(mapping.TrackerCategory);
|
||||
cats.Add(trackerCategoryInt + 100000);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
// mapping.TrackerCategory is not an integer, continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return cats;
|
||||
}
|
||||
|
||||
private IEnumerable<ReleaseInfo> CleanLinks(IEnumerable<ReleaseInfo> releases)
|
||||
{
|
||||
if (string.IsNullOrEmpty(downloadUrlBase))
|
||||
return releases;
|
||||
foreach (var release in releases)
|
||||
{
|
||||
if (release.Link.ToString().StartsWith(downloadUrlBase, StringComparison.Ordinal))
|
||||
{
|
||||
release.Link = new Uri(release.Link.ToString().Substring(downloadUrlBase.Length), UriKind.Relative);
|
||||
}
|
||||
}
|
||||
|
||||
return releases;
|
||||
}
|
||||
|
||||
public override async Task<IEnumerable<ReleaseInfo>> ResultsForQuery(TorznabQuery query)
|
||||
{
|
||||
var results = await base.ResultsForQuery(query);
|
||||
results = CleanLinks(results);
|
||||
|
||||
return results;
|
||||
}
|
||||
protected abstract Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query);
|
||||
|
||||
protected virtual Uri UncleanLink(Uri link)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(downloadUrlBase))
|
||||
{
|
||||
return link;
|
||||
}
|
||||
|
||||
if (link.ToString().StartsWith(downloadUrlBase, StringComparison.Ordinal))
|
||||
{
|
||||
return link;
|
||||
}
|
||||
|
||||
return new Uri(downloadUrlBase + link.ToString(), UriKind.RelativeOrAbsolute);
|
||||
}
|
||||
|
||||
protected void OnParseError(string results, Exception ex)
|
||||
{
|
||||
var fileName = string.Format("Error on {0} for {1}.txt", DateTime.Now.ToString("yyyyMMddHHmmss"), DisplayName);
|
||||
var spacing = string.Join("", Enumerable.Repeat(Environment.NewLine, 5));
|
||||
var fileContents = string.Format("{0}{1}{2}", ex, spacing, results);
|
||||
logger.Error(fileName + fileContents);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
public override TorznabCapabilities TorznabCaps { get; protected set; }
|
||||
public Encoding Encoding { get; protected set; }
|
||||
|
||||
private List<CategoryMapping> categoryMapping = new List<CategoryMapping>();
|
||||
protected IWebClient webclient;
|
||||
protected readonly string downloadUrlBase = "";
|
||||
}
|
||||
|
||||
public abstract class BaseCachingWebIndexer : BaseWebIndexer
|
||||
{
|
||||
protected BaseCachingWebIndexer(string name, string link, string description, IIndexerConfigurationService configService, IWebClient client, Logger logger, ConfigurationData configData, IProtectionService p, TorznabCapabilities caps = null, string downloadBase = null)
|
||||
: base(name, link, description, configService, client, logger, configData, p, caps, downloadBase)
|
||||
{
|
||||
}
|
||||
|
||||
protected void CleanCache()
|
||||
{
|
||||
foreach (var expired in cache.Where(i => DateTime.Now - i.Created > cacheTime).ToList())
|
||||
{
|
||||
cache.Remove(expired);
|
||||
}
|
||||
}
|
||||
|
||||
protected static List<CachedQueryResult> cache = new List<CachedQueryResult>();
|
||||
protected static readonly TimeSpan cacheTime = new TimeSpan(0, 9, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ using System.Text;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class BestFriends : BaseIndexer
|
||||
public class BestFriends : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
string TakeLoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
|
@ -27,12 +27,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public BestFriends(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public BestFriends(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "Best Friends",
|
||||
description: "A German general tracker.",
|
||||
link: "http://bf.mine.nu/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -16,7 +16,7 @@ using System.Text;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class BeyondHD : BaseIndexer
|
||||
public class BeyondHD : BaseWebIndexer
|
||||
{
|
||||
private string SearchUrl { get { return SiteLink + "browse.php?searchin=title&incldead=0&"; } }
|
||||
|
||||
|
@ -26,12 +26,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public BeyondHD(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public BeyondHD(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "BeyondHD",
|
||||
description: "Without BeyondHD, your HDTV is just a TV",
|
||||
link: "https://beyond-hd.me/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -16,7 +16,7 @@ using System.Collections.Specialized;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class BitCityReloaded : BaseIndexer
|
||||
public class BitCityReloaded : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
string BrowseUrl { get { return SiteLink + "uebersicht.php"; } }
|
||||
|
@ -28,12 +28,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public BitCityReloaded(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public BitCityReloaded(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "Bit-City Reloaded",
|
||||
description: "A German general tracker.",
|
||||
link: "https://bc-reloaded.net/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -19,7 +19,7 @@ using System.Collections.Specialized;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class BitHdtv : BaseIndexer
|
||||
public class BitHdtv : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string TakeLoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
|
@ -32,12 +32,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public BitHdtv(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public BitHdtv(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "BIT-HDTV",
|
||||
description: "Home of high definition invites",
|
||||
link: "https://www.bit-hdtv.com/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -19,7 +19,7 @@ using System.Web;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class BitMeTV : BaseIndexer
|
||||
public class BitMeTV : BaseWebIndexer
|
||||
{
|
||||
//https is poorly implemented on BitMeTV. Site uses http to login, but then redirects to https for search
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
|
@ -33,12 +33,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public BitMeTV(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps)
|
||||
public BitMeTV(IIndexerConfigurationService configService, Logger l, IWebClient c, IProtectionService ps)
|
||||
: base(name: "BitMeTV",
|
||||
description: "TV Episode specialty tracker",
|
||||
link: "http://www.bitmetv.org/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: c,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -20,7 +20,7 @@ using System.Text.RegularExpressions;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class BitSoup : BaseIndexer
|
||||
public class BitSoup : BaseWebIndexer
|
||||
{
|
||||
private string BrowseUrl { get { return SiteLink + "browse.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
|
@ -33,12 +33,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public BitSoup(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public BitSoup(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "BitSoup",
|
||||
description: "SoupieBits",
|
||||
link: "https://www.bitsoup.me/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -20,7 +20,7 @@ using Newtonsoft.Json;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class BroadcastTheNet : BaseIndexer
|
||||
public class BroadcastTheNet : BaseWebIndexer
|
||||
{
|
||||
string APIBASE = "https://api.broadcasthe.net";
|
||||
|
||||
|
@ -30,12 +30,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public BroadcastTheNet(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public BroadcastTheNet(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "BroadcastTheNet",
|
||||
description: "Needs no description..",
|
||||
link: "https://broadcasthe.net/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -8,11 +8,11 @@ namespace Jackett.Indexers
|
|||
{
|
||||
public class BrokenStones : GazelleTracker
|
||||
{
|
||||
public BrokenStones(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
public BrokenStones(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
: base(name: "BrokenStones",
|
||||
desc: null,
|
||||
link: "https://brokenstones.club/",
|
||||
indexerManager: indexerManager,
|
||||
configService: configService,
|
||||
logger: logger,
|
||||
protectionService: protectionService,
|
||||
webClient: webClient
|
||||
|
|
|
@ -10,8 +10,6 @@ using System;
|
|||
using Jackett.Models.IndexerConfig;
|
||||
using System.Collections.Specialized;
|
||||
using System.Text;
|
||||
using YamlDotNet.Serialization;
|
||||
using YamlDotNet.Serialization.NamingConventions;
|
||||
using static Jackett.Models.IndexerConfig.ConfigurationData;
|
||||
using AngleSharp.Parser.Html;
|
||||
using System.Text.RegularExpressions;
|
||||
|
@ -22,11 +20,10 @@ using System.Linq;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class CardigannIndexer : BaseIndexer
|
||||
public class CardigannIndexer : BaseWebIndexer
|
||||
{
|
||||
public string DefinitionString { get; protected set; }
|
||||
protected IndexerDefinition Definition;
|
||||
public override string ID { get { return (Definition != null ? Definition.Site : GetIndexerID (GetType ())); } }
|
||||
public override string ID { get { return (Definition != null ? Definition.Site : GetIndexerID(GetType())); } }
|
||||
|
||||
protected WebClientStringResult landingResult;
|
||||
protected IHtmlDocument landingResultDocument;
|
||||
|
@ -37,228 +34,19 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
// A Dictionary allowing the same key multiple times
|
||||
public class KeyValuePairList : List<KeyValuePair<string, selectorBlock>>, IDictionary<string, selectorBlock>
|
||||
{
|
||||
public selectorBlock this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
base.Add(new KeyValuePair<string, selectorBlock>(key, value));
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<string> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<selectorBlock> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(string key, selectorBlock value)
|
||||
{
|
||||
base.Add(new KeyValuePair<string, selectorBlock>(key, value));
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out selectorBlock value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
// Cardigann yaml classes
|
||||
public class IndexerDefinition {
|
||||
public string Site { get; set; }
|
||||
public List<settingsField> Settings { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Language { get; set; }
|
||||
public string Encoding { get; set; }
|
||||
public List<string> Links { get; set; }
|
||||
public List<string> Certificates { get; set; }
|
||||
public capabilitiesBlock Caps { get; set; }
|
||||
public loginBlock Login { get; set; }
|
||||
public ratioBlock Ratio { get; set; }
|
||||
public searchBlock Search { get; set; }
|
||||
public downloadBlock Download { get; set; }
|
||||
// IndexerDefinitionStats not needed/implemented
|
||||
}
|
||||
public class settingsField
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Label { get; set; }
|
||||
public string Default { get; set; }
|
||||
public Dictionary<string, string> Options { get; set; }
|
||||
}
|
||||
|
||||
public class CategorymappingBlock
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string cat { get; set; }
|
||||
public string desc { get; set; }
|
||||
}
|
||||
|
||||
public class capabilitiesBlock
|
||||
{
|
||||
public Dictionary<string, string> Categories { get; set; }
|
||||
public List<CategorymappingBlock> Categorymappings { get; set; }
|
||||
public Dictionary<string, List<string>> Modes { get; set; }
|
||||
}
|
||||
|
||||
public class captchaBlock
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public string Image { get; set; }
|
||||
public string Input { get; set; }
|
||||
}
|
||||
|
||||
public class loginBlock
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string Submitpath { get; set; }
|
||||
public List<string> Cookies { get; set; }
|
||||
public string Method { get; set; }
|
||||
public string Form { get; set; }
|
||||
public bool Selectors { get; set; } = false;
|
||||
public Dictionary<string, string> Inputs { get; set; }
|
||||
public Dictionary<string, selectorBlock> Selectorinputs { get; set; }
|
||||
public Dictionary<string, selectorBlock> Getselectorinputs { get; set; }
|
||||
public List<errorBlock> Error { get; set; }
|
||||
public pageTestBlock Test { get; set; }
|
||||
public captchaBlock Captcha { get; set; }
|
||||
}
|
||||
|
||||
public class errorBlock
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string Selector { get; set; }
|
||||
public selectorBlock Message { get; set; }
|
||||
}
|
||||
|
||||
public class selectorBlock
|
||||
{
|
||||
public string Selector { get; set; }
|
||||
public bool Optional { get; set; } = false;
|
||||
public string Text { get; set; }
|
||||
public string Attribute { get; set; }
|
||||
public string Remove { get; set; }
|
||||
public List<filterBlock> Filters { get; set; }
|
||||
public Dictionary<string, string> Case { get; set; }
|
||||
}
|
||||
|
||||
public class filterBlock
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public dynamic Args { get; set; }
|
||||
}
|
||||
|
||||
public class pageTestBlock
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string Selector { get; set; }
|
||||
}
|
||||
|
||||
public class ratioBlock : selectorBlock
|
||||
{
|
||||
public string Path { get; set; }
|
||||
}
|
||||
|
||||
public class searchBlock
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public List<searchPathBlock> Paths { get; set; }
|
||||
public Dictionary<string, List<string>> Headers { get; set; }
|
||||
public List<filterBlock> Keywordsfilters { get; set; }
|
||||
public Dictionary<string, string> Inputs { get; set; }
|
||||
public List<errorBlock> Error { get; set; }
|
||||
public rowsBlock Rows { get; set; }
|
||||
public KeyValuePairList Fields { get; set; }
|
||||
}
|
||||
|
||||
public class rowsBlock : selectorBlock
|
||||
{
|
||||
public int After { get; set; }
|
||||
//public string Remove { get; set; } // already inherited
|
||||
public selectorBlock Dateheaders { get; set; }
|
||||
}
|
||||
|
||||
public class searchPathBlock : requestBlock
|
||||
{
|
||||
public List<string> Categories { get; set; }
|
||||
public bool Inheritinputs { get; set; } = true;
|
||||
}
|
||||
|
||||
public class requestBlock
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string Method { get; set; }
|
||||
public Dictionary<string, string> Inputs { get; set; }
|
||||
}
|
||||
|
||||
public class downloadBlock
|
||||
{
|
||||
public string Selector { get; set; }
|
||||
public string Method { get; set; }
|
||||
public requestBlock Before { get; set; }
|
||||
}
|
||||
|
||||
protected readonly string[] OptionalFileds = new string[] { "imdb", "rageid", "tvdbid", "banner" };
|
||||
|
||||
public CardigannIndexer(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(manager: i,
|
||||
public CardigannIndexer(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps, IndexerDefinition Definition)
|
||||
: base(configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps)
|
||||
{
|
||||
}
|
||||
|
||||
public CardigannIndexer(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps, string DefinitionString)
|
||||
: base(manager: i,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps)
|
||||
{
|
||||
Init(DefinitionString);
|
||||
}
|
||||
|
||||
protected void Init(string DefinitionString)
|
||||
{
|
||||
this.DefinitionString = DefinitionString;
|
||||
var deserializer = new DeserializerBuilder()
|
||||
.WithNamingConvention(new CamelCaseNamingConvention())
|
||||
.IgnoreUnmatchedProperties()
|
||||
.Build();
|
||||
Definition = deserializer.Deserialize<IndexerDefinition>(DefinitionString);
|
||||
this.Definition = Definition;
|
||||
|
||||
// Add default data if necessary
|
||||
if (Definition.Settings == null)
|
||||
{
|
||||
{
|
||||
Definition.Settings = new List<settingsField>();
|
||||
Definition.Settings.Add(new settingsField { Name = "username", Label = "Username", Type = "text" });
|
||||
Definition.Settings.Add(new settingsField { Name = "password", Label = "Password", Type = "password" });
|
||||
|
@ -310,11 +98,11 @@ namespace Jackett.Indexers
|
|||
switch (Setting.Type)
|
||||
{
|
||||
case "checkbox":
|
||||
item = new BoolItem {Value = false};
|
||||
item = new BoolItem { Value = false };
|
||||
|
||||
if (Setting.Default != null && Setting.Default == "true")
|
||||
{
|
||||
((BoolItem) item).Value = true;
|
||||
((BoolItem)item).Value = true;
|
||||
}
|
||||
break;
|
||||
case "password":
|
||||
|
@ -337,13 +125,13 @@ namespace Jackett.Indexers
|
|||
{
|
||||
item = new StringItem { Value = Setting.Default }; ;
|
||||
}
|
||||
|
||||
|
||||
item.Name = Setting.Label;
|
||||
configData.AddDynamic(Setting.Name, item);
|
||||
}
|
||||
|
||||
if (Definition.Caps.Categories != null)
|
||||
{
|
||||
{
|
||||
foreach (var Category in Definition.Caps.Categories)
|
||||
{
|
||||
var cat = TorznabCatType.GetCatByName(Category.Value);
|
||||
|
@ -406,10 +194,10 @@ namespace Jackett.Indexers
|
|||
value = ((SelectItem)item).Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
value = ((StringItem)item).Value;
|
||||
}
|
||||
variables[".Config."+Setting.Name] = value;
|
||||
variables[".Config." + Setting.Name] = value;
|
||||
}
|
||||
return variables;
|
||||
}
|
||||
|
@ -547,7 +335,7 @@ namespace Jackett.Indexers
|
|||
}
|
||||
return true; // no error
|
||||
}
|
||||
|
||||
|
||||
protected async Task<bool> DoLogin()
|
||||
{
|
||||
var Login = Definition.Login;
|
||||
|
@ -581,7 +369,7 @@ namespace Jackett.Indexers
|
|||
var CaptchaConfigItem = (RecaptchaItem)configData.GetDynamic("Captcha");
|
||||
|
||||
if (CaptchaConfigItem != null)
|
||||
{
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(CaptchaConfigItem.Cookie))
|
||||
{
|
||||
// for remote users just set the cookie and return
|
||||
|
@ -594,7 +382,7 @@ namespace Jackett.Indexers
|
|||
{
|
||||
var CloudFlareQueryCollection = new NameValueCollection();
|
||||
CloudFlareQueryCollection["id"] = CloudFlareCaptchaChallenge.GetAttribute("data-ray");
|
||||
|
||||
|
||||
CloudFlareQueryCollection["g-recaptcha-response"] = CaptchaConfigItem.Value;
|
||||
var ClearanceUrl = resolvePath("/cdn-cgi/l/chk_captcha?" + CloudFlareQueryCollection.GetQueryString());
|
||||
|
||||
|
@ -660,13 +448,13 @@ namespace Jackett.Indexers
|
|||
|
||||
pairs[name] = value;
|
||||
}
|
||||
|
||||
|
||||
foreach (var Input in Definition.Login.Inputs)
|
||||
{
|
||||
var value = applyGoTemplateText(Input.Value);
|
||||
var input = Input.Key;
|
||||
if (Login.Selectors)
|
||||
{
|
||||
{
|
||||
var inputElement = landingResultDocument.QuerySelector(Input.Key);
|
||||
if (inputElement == null)
|
||||
throw new ExceptionWithConfigData(string.Format("Login failed: No input found using selector {0}", Input.Key), configData);
|
||||
|
@ -716,7 +504,7 @@ namespace Jackett.Indexers
|
|||
|
||||
// automatically solve simpleCaptchas, if used
|
||||
var simpleCaptchaPresent = landingResultDocument.QuerySelector("script[src*=\"simpleCaptcha\"]");
|
||||
if(simpleCaptchaPresent != null)
|
||||
if (simpleCaptchaPresent != null)
|
||||
{
|
||||
var captchaUrl = resolvePath("simpleCaptcha.php?numImages=1");
|
||||
var simpleCaptchaResult = await RequestStringWithCookies(captchaUrl.ToString(), null, LoginUrl);
|
||||
|
@ -736,7 +524,7 @@ namespace Jackett.Indexers
|
|||
{
|
||||
var input = Captcha.Input;
|
||||
if (Login.Selectors)
|
||||
{
|
||||
{
|
||||
var inputElement = landingResultDocument.QuerySelector(Captcha.Input);
|
||||
if (inputElement == null)
|
||||
throw new ExceptionWithConfigData(string.Format("Login failed: No captcha input found using {0}", Captcha.Input), configData);
|
||||
|
@ -771,9 +559,11 @@ namespace Jackett.Indexers
|
|||
bodyParts.Add("--" + boundary + "--");
|
||||
|
||||
headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
var body = string.Join("\r\n", bodyParts);
|
||||
var body = string.Join("\r\n", bodyParts);
|
||||
loginResult = await PostDataWithCookies(submitUrl.ToString(), pairs, configData.CookieHeader.Value, SiteLink, headers, body);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
loginResult = await RequestLoginAndFollowRedirect(submitUrl.ToString(), pairs, configData.CookieHeader.Value, true, null, LoginUrl, true);
|
||||
}
|
||||
|
||||
|
@ -903,7 +693,8 @@ namespace Jackett.Indexers
|
|||
if (Captcha.Type == "image")
|
||||
{
|
||||
var captchaElement = landingResultDocument.QuerySelector(Captcha.Image);
|
||||
if (captchaElement != null) {
|
||||
if (captchaElement != null)
|
||||
{
|
||||
hasCaptcha = true;
|
||||
|
||||
var CaptchaUrl = resolvePath(captchaElement.GetAttribute("src"), LoginUrl);
|
||||
|
@ -954,7 +745,7 @@ namespace Jackett.Indexers
|
|||
if (Filters == null)
|
||||
return Data;
|
||||
|
||||
foreach(filterBlock Filter in Filters)
|
||||
foreach (filterBlock Filter in Filters)
|
||||
{
|
||||
switch (Filter.Name)
|
||||
{
|
||||
|
@ -974,7 +765,7 @@ namespace Jackett.Indexers
|
|||
{
|
||||
logger.Debug(ex.Message);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case "regexp":
|
||||
var pattern = (string)Filter.Args;
|
||||
var Regexp = new Regex(pattern);
|
||||
|
@ -987,7 +778,7 @@ namespace Jackett.Indexers
|
|||
regexpreplace_replacement = applyGoTemplateText(regexpreplace_replacement, variables);
|
||||
Regex regexpreplace_regex = new Regex(regexpreplace_pattern);
|
||||
Data = regexpreplace_regex.Replace(Data, regexpreplace_replacement);
|
||||
break;
|
||||
break;
|
||||
case "split":
|
||||
var sep = (string)Filter.Args[0];
|
||||
var pos = (string)Filter.Args[1];
|
||||
|
@ -1097,7 +888,7 @@ namespace Jackett.Indexers
|
|||
|
||||
if (Selector.Remove != null)
|
||||
{
|
||||
foreach(var i in selection.QuerySelectorAll(Selector.Remove))
|
||||
foreach (var i in selection.QuerySelectorAll(Selector.Remove))
|
||||
{
|
||||
i.Remove();
|
||||
}
|
||||
|
@ -1105,7 +896,7 @@ namespace Jackett.Indexers
|
|||
|
||||
if (Selector.Case != null)
|
||||
{
|
||||
foreach(var Case in Selector.Case)
|
||||
foreach (var Case in Selector.Case)
|
||||
{
|
||||
if (selection.Matches(Case.Key) || QuerySelector(selection, Case.Key) != null)
|
||||
{
|
||||
|
@ -1113,7 +904,7 @@ namespace Jackett.Indexers
|
|||
break;
|
||||
}
|
||||
}
|
||||
if(value == null)
|
||||
if (value == null)
|
||||
throw new Exception(string.Format("None of the case selectors \"{0}\" matched {1}", string.Join(",", Selector.Case), selection.ToHtmlPretty()));
|
||||
}
|
||||
else if (Selector.Attribute != null)
|
||||
|
@ -1217,7 +1008,7 @@ namespace Jackett.Indexers
|
|||
InputsList.Add(SearchPath.Inputs);
|
||||
|
||||
foreach (var Inputs in InputsList)
|
||||
{
|
||||
{
|
||||
if (Inputs != null)
|
||||
{
|
||||
foreach (var Input in Inputs)
|
||||
|
@ -1467,7 +1258,8 @@ namespace Jackett.Indexers
|
|||
value = release.TVDBId.ToString();
|
||||
break;
|
||||
case "banner":
|
||||
if(!string.IsNullOrWhiteSpace(value)) {
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
var bannerurl = resolvePath(value, searchUrlUri);
|
||||
release.BannerUrl = bannerurl;
|
||||
}
|
||||
|
@ -1531,7 +1323,7 @@ namespace Jackett.Indexers
|
|||
var PrevRow = Row.PreviousElementSibling;
|
||||
string value = null;
|
||||
if (PrevRow == null) // continue with parent
|
||||
{
|
||||
{
|
||||
var Parent = Row.ParentElement;
|
||||
if (Parent != null)
|
||||
PrevRow = Parent.PreviousElementSibling;
|
||||
|
@ -1557,7 +1349,7 @@ namespace Jackett.Indexers
|
|||
PrevRow = Parent.PreviousElementSibling;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (value == null && DateHeaders.Optional == false)
|
||||
throw new Exception(string.Format("No date header row found for {0}", release.ToString()));
|
||||
if (value != null)
|
||||
|
|
|
@ -20,11 +20,11 @@ namespace Jackett.Indexers
|
|||
{
|
||||
public class CinemaZ : AvistazTracker
|
||||
{
|
||||
public CinemaZ(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
public CinemaZ(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
: base(name: "CinemaZ",
|
||||
desc: "Part of the Avistaz network.",
|
||||
link: "https://cinemaz.to/",
|
||||
indexerManager: indexerManager,
|
||||
configService: configService,
|
||||
logger: logger,
|
||||
protectionService: protectionService,
|
||||
webClient: webClient
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using CsQuery;
|
||||
using CsQuery;
|
||||
using Jackett.Models;
|
||||
using Jackett.Services;
|
||||
using Jackett.Utils.Clients;
|
||||
|
@ -18,7 +18,7 @@ using Jackett.Utils;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class DanishBits : BaseIndexer
|
||||
public class DanishBits : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "torrents.php"; } }
|
||||
|
@ -29,12 +29,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public DanishBits(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps)
|
||||
public DanishBits(IIndexerConfigurationService configService, Logger l, IWebClient c, IProtectionService ps)
|
||||
: base(name: "DanishBits",
|
||||
description: "A danish closed torrent tracker",
|
||||
link: "https://danishbits.org/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: c,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -16,7 +16,7 @@ using System.Web;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class Demonoid : BaseIndexer
|
||||
public class Demonoid : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "account_handler.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "files/?category={0}&subcategory=All&quality=All&seeded=2&to=1&query={1}&external=2"; } }
|
||||
|
@ -27,12 +27,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Demonoid(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
|
||||
public Demonoid(IIndexerConfigurationService configService, Logger l, IWebClient wc, IProtectionService ps)
|
||||
: base(name: "Demonoid",
|
||||
description: "Demonoid",
|
||||
link: "https://www.demonoid.pw/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -17,7 +17,7 @@ using System.IO;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class DigitalHive : BaseIndexer
|
||||
public class DigitalHive : BaseWebIndexer
|
||||
{
|
||||
private string SearchUrl { get { return SiteLink + "browse.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "login.php?returnto=%2F"; } }
|
||||
|
@ -29,12 +29,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public DigitalHive(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public DigitalHive(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "DigitalHive",
|
||||
description: "DigitalHive is one of the oldest general trackers",
|
||||
link: "https://www.digitalhive.org/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -18,7 +18,7 @@ using Jackett.Utils.Clients;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
class EliteTracker : BaseIndexer
|
||||
class EliteTracker : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
string BrowseUrl { get { return SiteLink + "browse.php"; } }
|
||||
|
@ -29,11 +29,11 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public EliteTracker(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
public EliteTracker(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
: base(name: "Elite-Tracker",
|
||||
description: "French Torrent Tracker",
|
||||
link: "https://elite-tracker.net/",
|
||||
manager: indexerManager,
|
||||
configService: configService,
|
||||
logger: logger,
|
||||
p: protectionService,
|
||||
client: webClient,
|
||||
|
|
|
@ -21,7 +21,7 @@ using System.Text.RegularExpressions;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class FileList : BaseIndexer
|
||||
public class FileList : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
string BrowseUrl { get { return SiteLink + "browse.php"; } }
|
||||
|
@ -32,12 +32,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public FileList(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public FileList(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "FileList",
|
||||
description: "The best Romanian site.",
|
||||
link: "http://filelist.ro/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -14,7 +14,7 @@ using System.Collections.Specialized;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class FunFile : BaseIndexer
|
||||
public class FunFile : BaseWebIndexer
|
||||
{
|
||||
private string SearchUrl { get { return SiteLink + "browse.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
|
@ -25,12 +25,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public FunFile(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public FunFile(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "FunFile",
|
||||
description: "A general tracker",
|
||||
link: "https://www.funfile.org/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -20,7 +20,7 @@ using System.Threading;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class Fuzer : BaseIndexer
|
||||
public class Fuzer : BaseWebIndexer
|
||||
{
|
||||
private string SearchUrl { get { return SiteLink + "index.php?name=torrents&"; } }
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
|
@ -32,11 +32,11 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Fuzer(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public Fuzer(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "Fuzer",
|
||||
description: "Fuzer is a private torrent website with israeli torrents.",
|
||||
link: "https://fuzer.me/",
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Jackett.Indexers
|
|||
//
|
||||
// Quick and dirty indexer for GFTracker.
|
||||
//
|
||||
public class GFTracker : BaseIndexer
|
||||
public class GFTracker : BaseWebIndexer
|
||||
{
|
||||
private string StartPageUrl { get { return SiteLink + "login.php?returnto=%2F"; } }
|
||||
private string LoginUrl { get { return SiteLink + "loginsite.php"; } }
|
||||
|
@ -34,12 +34,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public GFTracker(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public GFTracker(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "GFTracker",
|
||||
description: "Home of user happiness",
|
||||
link: "https://www.thegft.org/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -16,7 +16,7 @@ using Jackett.Models.IndexerConfig;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class GhostCity : BaseIndexer
|
||||
public class GhostCity : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
string BrowsePage { get { return SiteLink + "browse.php"; } }
|
||||
|
@ -27,12 +27,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public GhostCity(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public GhostCity(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "Ghost City",
|
||||
description: "A German general tracker",
|
||||
link: "http://ghostcity.dyndns.info/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
|
@ -18,7 +18,7 @@ using NLog;
|
|||
namespace Jackett.Indexers
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public class GimmePeers : BaseIndexer
|
||||
public class GimmePeers : BaseWebIndexer
|
||||
{
|
||||
private string BrowseUrl => SiteLink + "browse.php";
|
||||
private string LoginUrl => SiteLink + "takelogin.php";
|
||||
|
@ -29,12 +29,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public GimmePeers(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public GimmePeers(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "GimmePeers",
|
||||
description: "Formerly ILT",
|
||||
link: "https://www.gimmepeers.com/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -16,7 +16,7 @@ using AngleSharp.Parser.Html;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class HD4Free : BaseIndexer
|
||||
public class HD4Free : BaseWebIndexer
|
||||
{
|
||||
private string SearchUrl { get { return SiteLink + "ajax/initial_recall.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
|
@ -28,12 +28,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public HD4Free(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public HD4Free(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "HD4Free",
|
||||
description: "A HD trackers",
|
||||
link: "https://hd4free.xyz/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -8,11 +8,11 @@ namespace Jackett.Indexers
|
|||
{
|
||||
public class HDForever : GazelleTracker
|
||||
{
|
||||
public HDForever(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
public HDForever(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
: base(name: "HD-Forever",
|
||||
desc: null,
|
||||
link: "https://hdf.world/",
|
||||
indexerManager: indexerManager,
|
||||
configService: configService,
|
||||
logger: logger,
|
||||
protectionService: protectionService,
|
||||
webClient: webClient
|
||||
|
|
|
@ -11,11 +11,11 @@ namespace Jackett.Indexers
|
|||
{
|
||||
public class HDOnly : GazelleTracker
|
||||
{
|
||||
public HDOnly(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
public HDOnly(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
: base(name: "HD-Only",
|
||||
desc: null,
|
||||
link: "https://hd-only.org/",
|
||||
indexerManager: indexerManager,
|
||||
configService: configService,
|
||||
logger: logger,
|
||||
protectionService: protectionService,
|
||||
webClient: webClient
|
||||
|
|
|
@ -18,7 +18,7 @@ using System.Collections.Specialized;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class HDSpace : BaseIndexer
|
||||
public class HDSpace : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "index.php?page=login"; } }
|
||||
private string SearchUrl { get { return SiteLink + "index.php?page=torrents&"; } }
|
||||
|
@ -29,12 +29,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public HDSpace(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public HDSpace(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "HD-Space",
|
||||
description: "Sharing The Universe",
|
||||
link: "https://hd-space.org/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -19,7 +19,7 @@ using System.Collections.Specialized;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class HDTorrents : BaseIndexer
|
||||
public class HDTorrents : BaseWebIndexer
|
||||
{
|
||||
private string SearchUrl { get { return SiteLink + "torrents.php?"; } }
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
|
@ -32,11 +32,11 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public HDTorrents(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public HDTorrents(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "HD-Torrents",
|
||||
description: "HD-Torrents is a private torrent website with HD torrents and strict rules on their content.",
|
||||
link: "https://hdts.ru/",// Of the accessible domains the .ru seems the most reliable. https://hdts.ru | https://hd-torrents.org | https://hd-torrents.net | https://hd-torrents.me
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Jackett.Models;
|
||||
using Jackett.Models;
|
||||
using Jackett.Services;
|
||||
using Jackett.Utils;
|
||||
using Jackett.Utils.Clients;
|
||||
|
@ -15,7 +15,7 @@ using System.Globalization;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class Hardbay : BaseIndexer
|
||||
public class Hardbay : BaseWebIndexer
|
||||
{
|
||||
private string SearchUrl { get { return SiteLink + "api/v1/torrents"; } }
|
||||
private string LoginUrl { get { return SiteLink + "api/v1/auth"; } }
|
||||
|
@ -26,12 +26,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Hardbay(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public Hardbay(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "Hardbay",
|
||||
description: null,
|
||||
link: "https://hardbay.club/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -16,7 +16,7 @@ using System.Text;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class Hebits : BaseIndexer
|
||||
public class Hebits : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string LoginPostUrl { get { return SiteLink + "takeloginAjax.php"; } }
|
||||
|
@ -28,12 +28,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Hebits(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
|
||||
public Hebits(IIndexerConfigurationService configService, Logger l, IWebClient wc, IProtectionService ps)
|
||||
: base(name: "Hebits",
|
||||
description: "The Israeli Tracker",
|
||||
link: "https://hebits.net/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using CsQuery;
|
||||
using CsQuery;
|
||||
using Jackett.Indexers;
|
||||
using Jackett.Models;
|
||||
using Jackett.Services;
|
||||
|
@ -23,7 +23,7 @@ using System.Text.RegularExpressions;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class Hounddawgs : BaseIndexer
|
||||
public class Hounddawgs : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "torrents.php"; } }
|
||||
|
@ -34,12 +34,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Hounddawgs(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps)
|
||||
public Hounddawgs(IIndexerConfigurationService configService, Logger l, IWebClient c, IProtectionService ps)
|
||||
: base(name: "Hounddawgs",
|
||||
description: "A danish closed torrent tracker",
|
||||
link: "https://hounddawgs.org/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: c,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -17,7 +17,7 @@ using System.Text.RegularExpressions;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class HouseOfTorrents : BaseIndexer
|
||||
public class HouseOfTorrents : BaseWebIndexer
|
||||
{
|
||||
private string SearchUrl { get { return SiteLink + "browse.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
|
@ -29,12 +29,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public HouseOfTorrents(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public HouseOfTorrents(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "House-of-Torrents",
|
||||
description: "A general tracker",
|
||||
link: "https://houseoftorrents.club/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -37,15 +37,15 @@ namespace Jackett.Indexers
|
|||
void LoadFromSavedConfiguration(JToken jsonConfig);
|
||||
void SaveConfig();
|
||||
|
||||
void Unconfigure();
|
||||
|
||||
Task<IEnumerable<ReleaseInfo>> ResultsForQuery(TorznabQuery query);
|
||||
|
||||
IEnumerable<ReleaseInfo> FilterResults(TorznabQuery query, IEnumerable<ReleaseInfo> input);
|
||||
|
||||
Task<byte[]> Download(Uri link);
|
||||
|
||||
IEnumerable<ReleaseInfo> CleanLinks(IEnumerable<ReleaseInfo> releases);
|
||||
Uri UncleanLink(Uri link);
|
||||
|
||||
bool CanHandleQuery(TorznabQuery query);
|
||||
}
|
||||
|
||||
public interface IWebIndexer : IIndexer
|
||||
{
|
||||
Task<byte[]> Download(Uri link);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ using Jackett.Models.IndexerConfig;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class IPTorrents : BaseIndexer
|
||||
public class IPTorrents : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
string TakeLoginUrl { get { return SiteLink + "take_login.php"; } }
|
||||
|
@ -32,12 +32,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public IPTorrents(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public IPTorrents(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "IPTorrents",
|
||||
description: "Always a step ahead.",
|
||||
link: "https://iptorrents.com/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -18,7 +18,7 @@ using Jackett.Models.IndexerConfig;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class ImmortalSeed : BaseIndexer
|
||||
public class ImmortalSeed : BaseWebIndexer
|
||||
{
|
||||
private string BrowsePage { get { return SiteLink + "browse.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
|
@ -30,12 +30,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public ImmortalSeed(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public ImmortalSeed(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "ImmortalSeed",
|
||||
description: "ImmortalSeed",
|
||||
link: "http://immortalseed.me/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using CsQuery;
|
||||
using Jackett.Models;
|
||||
using Jackett.Models.IndexerConfig;
|
||||
using Jackett.Services;
|
||||
|
@ -13,10 +11,10 @@ using NLog;
|
|||
|
||||
namespace Jackett.Indexers.Meta
|
||||
{
|
||||
public abstract class BaseMetaIndexer : BaseIndexer
|
||||
public abstract class BaseMetaIndexer : BaseWebIndexer
|
||||
{
|
||||
protected BaseMetaIndexer(string name, string description, IFallbackStrategyProvider fallbackStrategyProvider, IResultFilterProvider resultFilterProvider, IIndexerManagerService manager, IWebClient webClient, Logger logger, ConfigurationData configData, IProtectionService p, Func<IIndexer, bool> filter)
|
||||
: base(name, "http://127.0.0.1/", description, manager, webClient, logger, configData, p, null, null)
|
||||
protected BaseMetaIndexer(string name, string description, IFallbackStrategyProvider fallbackStrategyProvider, IResultFilterProvider resultFilterProvider, IIndexerConfigurationService configService, IWebClient webClient, Logger logger, ConfigurationData configData, IProtectionService p, Func<IIndexer, bool> filter)
|
||||
: base(name, "http://127.0.0.1/", description, configService, webClient, logger, configData, p, null, null)
|
||||
{
|
||||
filterFunc = filter;
|
||||
this.fallbackStrategyProvider = fallbackStrategyProvider;
|
||||
|
@ -35,11 +33,12 @@ namespace Jackett.Indexers.Meta
|
|||
|
||||
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
IEnumerable<Task<IEnumerable<ReleaseInfo>>> supportedTasks = Indexers.Where(i => i.CanHandleQuery(query)).Select(i => i.ResultsForQuery(query)).ToList(); // explicit conversion to List to execute LINQ query
|
||||
var indexers = validIndexers;
|
||||
IEnumerable<Task<IEnumerable<ReleaseInfo>>> supportedTasks = indexers.Where(i => i.CanHandleQuery(query)).Select(i => i.ResultsForQuery(query)).ToList(); // explicit conversion to List to execute LINQ query
|
||||
|
||||
var fallbackStrategies = fallbackStrategyProvider.FallbackStrategiesForQuery(query);
|
||||
var fallbackQueries = fallbackStrategies.Select(async f => await f.FallbackQueries()).SelectMany(t => t.Result);
|
||||
var fallbackTasks = fallbackQueries.SelectMany(q => Indexers.Where(i => !i.CanHandleQuery(query) && i.CanHandleQuery(q)).Select(i => i.ResultsForQuery(q.Clone())));
|
||||
var fallbackTasks = fallbackQueries.SelectMany(q => indexers.Where(i => !i.CanHandleQuery(query) && i.CanHandleQuery(q)).Select(i => i.ResultsForQuery(q.Clone())));
|
||||
var tasks = supportedTasks.Concat(fallbackTasks.ToList()); // explicit conversion to List to execute LINQ query
|
||||
var aggregateTask = Task.WhenAll(tasks);
|
||||
|
||||
|
@ -66,47 +65,36 @@ namespace Jackett.Indexers.Meta
|
|||
return result;
|
||||
}
|
||||
|
||||
public override Uri UncleanLink(Uri link)
|
||||
public override TorznabCapabilities TorznabCaps
|
||||
{
|
||||
var indexer = GetOriginalIndexerForLink(link);
|
||||
if (indexer != null)
|
||||
return indexer.UncleanLink(link);
|
||||
|
||||
return base.UncleanLink(link);
|
||||
get
|
||||
{
|
||||
return validIndexers.Select(i => i.TorznabCaps).Aggregate(new TorznabCapabilities(), TorznabCapabilities.Concat);
|
||||
}
|
||||
}
|
||||
|
||||
public override Task<byte[]> Download(Uri link)
|
||||
public override bool IsConfigured
|
||||
{
|
||||
var indexer = GetOriginalIndexerForLink(link);
|
||||
if (indexer != null)
|
||||
return indexer.Download(link);
|
||||
|
||||
return base.Download(link);
|
||||
get
|
||||
{
|
||||
return Indexers != null;
|
||||
}
|
||||
}
|
||||
|
||||
private IIndexer GetOriginalIndexerForLink(Uri link)
|
||||
private IEnumerable<IIndexer> validIndexers
|
||||
{
|
||||
var prefix = string.Format("{0}://{1}", link.Scheme, link.Host);
|
||||
var validIndexers = Indexers.Where(i => i.SiteLink.StartsWith(prefix, StringComparison.CurrentCulture));
|
||||
if (validIndexers.Count() > 0)
|
||||
return validIndexers.First();
|
||||
get
|
||||
{
|
||||
if (Indexers == null)
|
||||
return null;
|
||||
|
||||
return null;
|
||||
return Indexers.Where(i => i.IsConfigured && filterFunc(i));
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<IIndexer> Indexers;
|
||||
|
||||
private Func<IIndexer, bool> filterFunc;
|
||||
private IEnumerable<IIndexer> indexers;
|
||||
public IEnumerable<IIndexer> Indexers {
|
||||
get {
|
||||
return indexers;
|
||||
}
|
||||
set {
|
||||
indexers = value.Where(i => i.IsConfigured && filterFunc(i));
|
||||
TorznabCaps = value.Select(i => i.TorznabCaps).Aggregate(new TorznabCapabilities(), TorznabCapabilities.Concat); ;
|
||||
IsConfigured = true;
|
||||
}
|
||||
}
|
||||
|
||||
private IFallbackStrategyProvider fallbackStrategyProvider;
|
||||
private IResultFilterProvider resultFilterProvider;
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ namespace Jackett.Indexers.Meta
|
|||
{
|
||||
class AggregateIndexer : BaseMetaIndexer
|
||||
{
|
||||
public AggregateIndexer(IFallbackStrategyProvider fallbackStrategyProvider, IResultFilterProvider resultFilterProvider, IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base("AggregateSearch", "This feed includes all configured trackers", fallbackStrategyProvider, resultFilterProvider, i, wc, l, new ConfigurationData(), ps, x => true)
|
||||
public AggregateIndexer(IFallbackStrategyProvider fallbackStrategyProvider, IResultFilterProvider resultFilterProvider, IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base("AggregateSearch", "This feed includes all configured trackers", fallbackStrategyProvider, resultFilterProvider, configService, wc, l, new ConfigurationData(), ps, x => true)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ using Jackett.Utils;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class MoreThanTV : BaseIndexer
|
||||
public class MoreThanTV : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl => SiteLink + "login.php";
|
||||
private string SearchUrl => SiteLink + "ajax.php?action=browse&searchstr=";
|
||||
|
@ -28,13 +28,13 @@ namespace Jackett.Indexers
|
|||
|
||||
private ConfigurationDataBasicLogin ConfigData => (ConfigurationDataBasicLogin) configData;
|
||||
|
||||
public MoreThanTV(IIndexerManagerService i, IWebClient c, Logger l, IProtectionService ps)
|
||||
public MoreThanTV(IIndexerConfigurationService configService, IWebClient c, Logger l, IProtectionService ps)
|
||||
: base(name: "MoreThanTV",
|
||||
description: "ROMANIAN Private Torrent Tracker for TV / MOVIES, and the internal tracker for the release group DRACULA.",
|
||||
link: "https://www.morethan.tv/",
|
||||
caps: new TorznabCapabilities(TorznabCatType.TV,
|
||||
TorznabCatType.Movies),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: c,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -21,7 +21,7 @@ using System.Globalization;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class Myanonamouse : BaseIndexer
|
||||
public class Myanonamouse : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "tor/js/loadSearch2.php"; } }
|
||||
|
@ -32,7 +32,7 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Myanonamouse(IIndexerManagerService i, IWebClient c, Logger l, IProtectionService ps)
|
||||
public Myanonamouse(IIndexerConfigurationService configService, IWebClient c, Logger l, IProtectionService ps)
|
||||
: base(name: "MyAnonamouse",
|
||||
description: "Friendliness, Warmth and Sharing",
|
||||
link: "https://www.myanonamouse.net/",
|
||||
|
@ -42,7 +42,7 @@ namespace Jackett.Indexers
|
|||
TorznabCatType.BooksEbook,
|
||||
TorznabCatType.BooksMagazines,
|
||||
TorznabCatType.BooksTechnical),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: c,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -16,7 +16,7 @@ using System.Text.RegularExpressions;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class NCore : BaseIndexer
|
||||
public class NCore : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "torrents.php"; } }
|
||||
|
@ -28,12 +28,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public NCore(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public NCore(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "nCore",
|
||||
description: "A Hungarian private torrent site.",
|
||||
link: "https://ncore.cc/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -15,7 +15,7 @@ using System.Text;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class NewRealWorld : BaseIndexer
|
||||
public class NewRealWorld : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
string BrowseUrl { get { return SiteLink + "browse.php"; } }
|
||||
|
@ -26,12 +26,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public NewRealWorld(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public NewRealWorld(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "New Real World",
|
||||
description: "A German general tracker.",
|
||||
link: "http://nrw-tracker.eu/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Jackett.Indexers
|
|||
/// <summary>s
|
||||
/// Provider for Norbits Private Tracker
|
||||
/// </summary>
|
||||
public class Norbits : BaseIndexer
|
||||
public class Norbits : BaseCachingWebIndexer
|
||||
{
|
||||
private string LoginUrl => SiteLink + "login.php";
|
||||
private string LoginCheckUrl => SiteLink + "takelogin.php";
|
||||
|
@ -39,13 +39,13 @@ namespace Jackett.Indexers
|
|||
private CQ _fDom;
|
||||
private ConfigurationDataNorbits ConfigData => (ConfigurationDataNorbits)configData;
|
||||
|
||||
public Norbits(IIndexerManagerService i, IWebClient w, Logger l, IProtectionService ps)
|
||||
public Norbits(IIndexerConfigurationService configService, IWebClient w, Logger l, IProtectionService ps)
|
||||
: base(
|
||||
name: "Norbits",
|
||||
description: "Norbits",
|
||||
link: "https://norbits.net/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
@ -182,7 +182,7 @@ namespace Jackett.Indexers
|
|||
var message = "Error during attempt !";
|
||||
// Parse redirect header
|
||||
var redirectTo = response.RedirectingTo;
|
||||
|
||||
|
||||
// Oops, unable to login
|
||||
Output("-> Login failed: " + message, "error");
|
||||
throw new ExceptionWithConfigData("Login failed: " + message, configData);
|
||||
|
@ -230,7 +230,7 @@ namespace Jackett.Indexers
|
|||
var searchUrl = SearchUrl;
|
||||
|
||||
// Check login before performing a query
|
||||
await CheckLogin();
|
||||
await CheckLogin();
|
||||
|
||||
// Check cache first so we don't query the server (if search term used or not in dev mode)
|
||||
if (!DevMode && !string.IsNullOrEmpty(exactSearchTerm))
|
||||
|
@ -285,7 +285,7 @@ namespace Jackett.Indexers
|
|||
else
|
||||
{
|
||||
// Check if no result
|
||||
if(torrentRowList.Count == 0)
|
||||
if (torrentRowList.Count == 0)
|
||||
{
|
||||
// No results found
|
||||
Output("\nNo result found for your query, please try another search term ...\n", "info");
|
||||
|
@ -314,7 +314,7 @@ namespace Jackett.Indexers
|
|||
// Category
|
||||
var categoryId = tRow.Find("td:eq(0) > div > a:eq(0)").Attr("href").Split('?').Last();
|
||||
var categoryName = tRow.Find("td:eq(0) > div > a:eq(0)").Attr("title");
|
||||
|
||||
|
||||
var MainCat = tRow.Find("td:eq(0) > div > a:eq(0)").Attr("href").Split('?').Last();
|
||||
var SubCat1 = "none";
|
||||
var SubCat2 = "none";
|
||||
|
@ -336,7 +336,7 @@ namespace Jackett.Indexers
|
|||
// Seeders
|
||||
var seeders = ParseUtil.CoerceInt(tRow.Find("td:eq(9)").Text());
|
||||
Output("Seeders: " + seeders);
|
||||
|
||||
|
||||
// Leechers
|
||||
var leechers = ParseUtil.CoerceInt(tRow.Find("td:eq(10)").Text());
|
||||
Output("Leechers: " + leechers);
|
||||
|
@ -594,7 +594,8 @@ namespace Jackett.Indexers
|
|||
.Select(f => new System.IO.FileInfo(f))
|
||||
.Where(f => f.LastAccessTime < DateTime.Now.AddMilliseconds(-Convert.ToInt32(ConfigData.HardDriveCacheKeepTime.Value)))
|
||||
.ToList()
|
||||
.ForEach(f => {
|
||||
.ForEach(f =>
|
||||
{
|
||||
Output("Deleting cached file << " + f.Name + " >> ... done.");
|
||||
f.Delete();
|
||||
i++;
|
||||
|
@ -605,7 +606,8 @@ namespace Jackett.Indexers
|
|||
{
|
||||
Output("-> Deleted " + i + " cached files during cleaning.");
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
Output("-> Nothing deleted during cleaning.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ using Jackett.Models.IndexerConfig;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class PassThePopcorn : BaseIndexer
|
||||
public class PassThePopcorn : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return "https://passthepopcorn.me/ajax.php?action=login"; } }
|
||||
private string indexUrl { get { return "https://passthepopcorn.me/ajax.php?action=login"; } }
|
||||
|
@ -29,12 +29,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public PassThePopcorn(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps)
|
||||
public PassThePopcorn(IIndexerConfigurationService configService, Logger l, IWebClient c, IProtectionService ps)
|
||||
: base(name: "PassThePopcorn",
|
||||
description: "PassThePopcorn",
|
||||
link: "https://passthepopcorn.me/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: c,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -17,7 +17,7 @@ using System.Collections.Specialized;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
class PiXELHD : BaseIndexer
|
||||
class PiXELHD : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
string BrowseUrl { get { return SiteLink + "torrents.php"; } }
|
||||
|
@ -32,12 +32,12 @@ namespace Jackett.Indexers
|
|||
string input_username = null;
|
||||
string input_password = null;
|
||||
|
||||
public PiXELHD(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
public PiXELHD(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
: base(name: "PiXELHD",
|
||||
description: null,
|
||||
link: "https://pixelhd.me/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: indexerManager,
|
||||
configService: configService,
|
||||
logger: logger,
|
||||
p: protectionService,
|
||||
client: webClient,
|
||||
|
|
|
@ -16,7 +16,7 @@ using System.Globalization;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class PirateTheNet : BaseIndexer
|
||||
public class PirateTheNet : BaseWebIndexer
|
||||
{
|
||||
private string SearchUrl { get { return SiteLink + "torrentsutils.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
|
@ -30,12 +30,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public PirateTheNet(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public PirateTheNet(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "PirateTheNet",
|
||||
description: "A movie tracker",
|
||||
link: "http://piratethenet.org/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -16,7 +16,7 @@ using System.Collections.Specialized;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class Pretome : BaseIndexer
|
||||
public class Pretome : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
private string LoginReferer { get { return SiteLink + "index.php?cat=1"; } }
|
||||
|
@ -30,13 +30,13 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Pretome(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public Pretome(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "PreToMe",
|
||||
description: "BitTorrent site for High Quality, High Definition (HD) movies and TV Shows",
|
||||
link: "https://pretome.info/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
client: wc,
|
||||
manager: i,
|
||||
configService: configService,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataPinNumber())
|
||||
|
|
|
@ -18,11 +18,11 @@ namespace Jackett.Indexers
|
|||
{
|
||||
public class PrivateHD : AvistazTracker, IIndexer
|
||||
{
|
||||
public PrivateHD(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
public PrivateHD(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
: base(name: "PrivateHD",
|
||||
desc: "BitTorrent site for High Quality, High Definition (HD) movies and TV Shows",
|
||||
link: "https://privatehd.to/",
|
||||
indexerManager: indexerManager,
|
||||
configService: configService,
|
||||
logger: logger,
|
||||
protectionService: protectionService,
|
||||
webClient: webClient
|
||||
|
|
|
@ -8,11 +8,11 @@ namespace Jackett.Indexers
|
|||
{
|
||||
public class Psytorrents : GazelleTracker
|
||||
{
|
||||
public Psytorrents(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
public Psytorrents(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
: base(name: "Psytorrents",
|
||||
desc: null,
|
||||
link: "https://psytorrents.info/",
|
||||
indexerManager: indexerManager,
|
||||
configService: configService,
|
||||
logger: logger,
|
||||
protectionService: protectionService,
|
||||
webClient: webClient
|
||||
|
|
|
@ -16,7 +16,7 @@ using System.Web;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class Rarbg : BaseIndexer
|
||||
public class Rarbg : BaseWebIndexer
|
||||
{
|
||||
readonly static string defaultSiteLink = "https://torrentapi.org/";
|
||||
|
||||
|
@ -41,12 +41,12 @@ namespace Jackett.Indexers
|
|||
|
||||
private bool HasValidToken { get { return !string.IsNullOrEmpty(token) && lastTokenFetch > DateTime.Now - TOKEN_DURATION; } }
|
||||
|
||||
public Rarbg(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public Rarbg(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "RARBG",
|
||||
description: null,
|
||||
link: "https://rarbg.to/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -8,11 +8,11 @@ namespace Jackett.Indexers
|
|||
{
|
||||
public class PassTheHeadphones : GazelleTracker
|
||||
{
|
||||
public PassTheHeadphones(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
public PassTheHeadphones(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
: base(name: "Redacted",
|
||||
desc: "A music tracker",
|
||||
link: "https://redacted.ch/",
|
||||
indexerManager: indexerManager,
|
||||
configService: configService,
|
||||
logger: logger,
|
||||
protectionService: protectionService,
|
||||
webClient: webClient
|
||||
|
|
|
@ -20,7 +20,7 @@ using System.Xml.Linq;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class RevolutionTT : BaseIndexer
|
||||
public class RevolutionTT : BaseWebIndexer
|
||||
{
|
||||
private string LandingPageURL { get { return SiteLink + "login.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
|
@ -36,12 +36,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public RevolutionTT(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
|
||||
public RevolutionTT(IIndexerConfigurationService configService, Logger l, IWebClient wc, IProtectionService ps)
|
||||
: base(name: "RevolutionTT",
|
||||
description: "The Revolution has begun",
|
||||
link: "https://revolutiontt.me/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -17,7 +17,7 @@ using System.Web;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
class SceneAccess : BaseIndexer
|
||||
class SceneAccess : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login"; } }
|
||||
private string SearchUrl { get { return SiteLink + "all?search={0}&method=2"; } }
|
||||
|
@ -28,12 +28,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public SceneAccess(IIndexerManagerService i, IWebClient c, Logger l, IProtectionService ps)
|
||||
public SceneAccess(IIndexerConfigurationService configService, IWebClient c, Logger l, IProtectionService ps)
|
||||
: base(name: "SceneAccess",
|
||||
description: "Your gateway to the scene",
|
||||
link: "https://sceneaccess.eu/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: c,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -15,7 +15,7 @@ using Jackett.Models.IndexerConfig;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class SceneFZ : BaseIndexer
|
||||
public class SceneFZ : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
|
||||
|
@ -27,12 +27,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public SceneFZ(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public SceneFZ(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "SceneFZ",
|
||||
description: "Torrent tracker. Tracking over 50.000 torrent files.",
|
||||
link: "http://scenefz.me/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -15,7 +15,7 @@ using System.Text.RegularExpressions;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class SceneTime : BaseIndexer
|
||||
public class SceneTime : BaseWebIndexer
|
||||
{
|
||||
private string StartPageUrl { get { return SiteLink + "login.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
|
@ -28,12 +28,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public SceneTime(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public SceneTime(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "SceneTime",
|
||||
description: "Always on time",
|
||||
link: "https://www.scenetime.com/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -22,7 +22,7 @@ using System.Xml.XPath;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class Shazbat : BaseIndexer
|
||||
public class Shazbat : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login"; } }
|
||||
private string SearchUrl { get { return SiteLink + "search"; } }
|
||||
|
@ -36,14 +36,14 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Shazbat(IIndexerManagerService i, IWebClient c, Logger l, IProtectionService ps)
|
||||
public Shazbat(IIndexerConfigurationService configService, IWebClient c, Logger l, IProtectionService ps)
|
||||
: base(name: "Shazbat",
|
||||
description: "Modern indexer",
|
||||
link: "https://www.shazbat.tv/",
|
||||
caps: new TorznabCapabilities(TorznabCatType.TV,
|
||||
TorznabCatType.TVHD,
|
||||
TorznabCatType.TVSD),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: c,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -15,7 +15,7 @@ using Jackett.Models.IndexerConfig;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class ShowRSS : BaseIndexer
|
||||
public class ShowRSS : BaseWebIndexer
|
||||
{
|
||||
private string SearchAllUrl { get { return SiteLink + "other/all.rss"; } }
|
||||
|
||||
|
@ -25,12 +25,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public ShowRSS(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
|
||||
public ShowRSS(IIndexerConfigurationService configService, Logger l, IWebClient wc, IProtectionService ps)
|
||||
: base(name: "ShowRSS",
|
||||
description: "showRSS is a service that allows you to keep track of your favorite TV shows",
|
||||
link: "http://showrss.info/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using CsQuery;
|
||||
using CsQuery;
|
||||
using Jackett.Models;
|
||||
using Jackett.Services;
|
||||
using Jackett.Utils;
|
||||
|
@ -16,7 +16,7 @@ using System.Collections.Specialized;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class SpeedCD : BaseIndexer
|
||||
public class SpeedCD : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "browse.php"; } }
|
||||
|
@ -27,12 +27,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public SpeedCD(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
|
||||
public SpeedCD(IIndexerConfigurationService configService, Logger l, IWebClient wc, IProtectionService ps)
|
||||
: base(name: "Speed.cd",
|
||||
description: "Your home now!",
|
||||
link: "https://speed.cd/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -15,7 +15,7 @@ using System.Globalization;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class Superbits : BaseIndexer
|
||||
public class Superbits : BaseWebIndexer
|
||||
{
|
||||
private string SearchUrl { get { return SiteLink + "api/v1/torrents"; } }
|
||||
private string LoginUrl { get { return SiteLink + "api/v1/auth"; } }
|
||||
|
@ -26,12 +26,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Superbits(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public Superbits(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "Superbits",
|
||||
description: null,
|
||||
link: "https://superbits.org/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Jackett.Models;
|
||||
using Jackett.Models;
|
||||
using Jackett.Services;
|
||||
using Jackett.Utils;
|
||||
using Jackett.Utils.Clients;
|
||||
|
@ -15,7 +15,7 @@ using Jackett.Models.IndexerConfig;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class T411 : BaseIndexer
|
||||
public class T411 : BaseWebIndexer
|
||||
{
|
||||
const string ApiUrl = "https://api.t411.al";
|
||||
const string AuthUrl = ApiUrl + "/auth";
|
||||
|
@ -32,12 +32,12 @@ namespace Jackett.Indexers
|
|||
|
||||
private Dictionary<int, List<int>> _mediaCategoryMapping = new Dictionary<int, List<int>>();
|
||||
|
||||
public T411(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
|
||||
public T411(IIndexerConfigurationService configService, Logger l, IWebClient wc, IProtectionService ps)
|
||||
: base(name: "T411",
|
||||
description: "French Torrent Tracker",
|
||||
link: "https://t411.al/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -21,7 +21,7 @@ using System.Xml.Linq;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class TVChaosUK : BaseIndexer
|
||||
public class TVChaosUK : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
string GetRSSKeyUrl { get { return SiteLink + "getrss.php"; } }
|
||||
|
@ -36,12 +36,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public TVChaosUK(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public TVChaosUK(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "TV Chaos",
|
||||
description: "Total Chaos",
|
||||
link: "https://www.tvchaosuk.com/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -15,7 +15,7 @@ using System.Text.RegularExpressions;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class TVVault : BaseIndexer
|
||||
public class TVVault : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
string BrowseUrl { get { return SiteLink + "torrents.php"; } }
|
||||
|
@ -26,12 +26,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public TVVault(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public TVVault(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "TV-Vault",
|
||||
description: "A TV tracker for old shows.",
|
||||
link: "https://tv-vault.me/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -16,7 +16,7 @@ using Jackett.Models.IndexerConfig;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class TehConnection : BaseIndexer
|
||||
public class TehConnection : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string indexUrl { get { return SiteLink + "index.php"; } }
|
||||
|
@ -28,12 +28,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public TehConnection(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps)
|
||||
public TehConnection(IIndexerConfigurationService configService, Logger l, IWebClient c, IProtectionService ps)
|
||||
: base(name: "TehConnection",
|
||||
description: "Working towards providing a well-seeded archive of all available digital forms of cinema and film in their highest possible quality",
|
||||
link: "https://tehconnection.eu/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: c,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -19,7 +19,7 @@ using Jackett.Models.IndexerConfig;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class TorrentBytes : BaseIndexer
|
||||
public class TorrentBytes : BaseWebIndexer
|
||||
{
|
||||
private string BrowseUrl { get { return SiteLink + "browse.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
|
@ -30,12 +30,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public TorrentBytes(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public TorrentBytes(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "TorrentBytes",
|
||||
description: "A decade of torrentbytes",
|
||||
link: "https://www.torrentbytes.net/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -19,7 +19,7 @@ using System.Collections.Specialized;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class TorrentDay : BaseIndexer
|
||||
public class TorrentDay : BaseWebIndexer
|
||||
{
|
||||
private string StartPageUrl { get { return SiteLink + "login.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "tak3login.php"; } }
|
||||
|
@ -44,12 +44,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public TorrentDay(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
|
||||
public TorrentDay(IIndexerConfigurationService configService, Logger l, IWebClient wc, IProtectionService ps)
|
||||
: base(name: "TorrentDay",
|
||||
description: "TorrentDay",
|
||||
link: "https://torrentday.it/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -17,7 +17,7 @@ using System.Text.RegularExpressions;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class TorrentHeaven : BaseIndexer
|
||||
public class TorrentHeaven : BaseWebIndexer
|
||||
{
|
||||
string IndexUrl { get { return SiteLink + "index.php"; } }
|
||||
string LoginCompleteUrl { get { return SiteLink + "index.php?strWebValue=account&strWebAction=login_complete&ancestry=verify"; } }
|
||||
|
@ -29,12 +29,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public TorrentHeaven(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public TorrentHeaven(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "TorrentHeaven",
|
||||
description: "A German general tracker.",
|
||||
link: "https://torrentheaven.myfqdn.info/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
@ -44,59 +44,53 @@ namespace Jackett.Indexers
|
|||
Language = "de-de";
|
||||
Type = "private";
|
||||
|
||||
AddCategoryMapping(1, TorznabCatType.PCGames); // GAMES/PC
|
||||
AddCategoryMapping(3, TorznabCatType.Console); // GAMES/Sonstige
|
||||
AddCategoryMapping(59, TorznabCatType.ConsolePS4); // GAMES/PlayStation
|
||||
AddCategoryMapping(60, TorznabCatType.ConsolePSP); // GAMES/PSP
|
||||
AddCategoryMapping(63, TorznabCatType.ConsoleWii); // GAMES/Wii
|
||||
AddCategoryMapping(67, TorznabCatType.ConsoleXbox360); // GAMES/XBOX 360
|
||||
AddCategoryMapping(68, TorznabCatType.PCPhoneOther); // GAMES/PDA / Handy
|
||||
AddCategoryMapping(72, TorznabCatType.ConsoleNDS); // GAMES/NDS
|
||||
AddCategoryMapping(1, TorznabCatType.PCGames); // GAMES/PC
|
||||
AddCategoryMapping(3, TorznabCatType.Console); // GAMES/Sonstige
|
||||
AddCategoryMapping(59, TorznabCatType.ConsolePS4); // GAMES/PlayStation
|
||||
AddCategoryMapping(60, TorznabCatType.ConsolePSP); // GAMES/PSP
|
||||
AddCategoryMapping(63, TorznabCatType.ConsoleWii); // GAMES/Wii
|
||||
AddCategoryMapping(67, TorznabCatType.ConsoleXbox360); // GAMES/XBOX 360
|
||||
AddCategoryMapping(68, TorznabCatType.PCPhoneOther); // GAMES/PDA / Handy
|
||||
AddCategoryMapping(72, TorznabCatType.ConsoleNDS); // GAMES/NDS
|
||||
|
||||
AddCategoryMapping(7 , TorznabCatType.MoviesDVD); // MOVIES/DVD
|
||||
AddCategoryMapping(8, TorznabCatType.MoviesSD); // MOVIES/SD
|
||||
AddCategoryMapping(37, TorznabCatType.MoviesDVD); // MOVIES/DVD Spezial
|
||||
AddCategoryMapping(41, TorznabCatType.MoviesForeign); // MOVIES/International
|
||||
AddCategoryMapping(7, TorznabCatType.MoviesDVD); // MOVIES/DVD
|
||||
AddCategoryMapping(8, TorznabCatType.MoviesSD); // MOVIES/SD
|
||||
AddCategoryMapping(37, TorznabCatType.MoviesDVD); // MOVIES/DVD Spezial
|
||||
AddCategoryMapping(41, TorznabCatType.MoviesForeign); // MOVIES/International
|
||||
AddCategoryMapping(101, TorznabCatType.MoviesHD); // MOVIES/720p
|
||||
AddCategoryMapping(102, TorznabCatType.MoviesHD); // MOVIES/1080p
|
||||
AddCategoryMapping(103, TorznabCatType.MoviesHD); // MOVIES/AVCHD
|
||||
AddCategoryMapping(104, TorznabCatType.MoviesBluRay); // MOVIES/Bluray
|
||||
AddCategoryMapping(106, TorznabCatType.Movies3D); // MOVIES/3D
|
||||
|
||||
AddCategoryMapping(14, TorznabCatType.Audio); // AUDIO/Musik
|
||||
AddCategoryMapping(15, TorznabCatType.AudioAudiobook); // AUDIO/Hörbücher
|
||||
AddCategoryMapping(16, TorznabCatType.AudioAudiobook); // AUDIO/Hörspiele
|
||||
AddCategoryMapping(36, TorznabCatType.AudioLossless); // AUDIO/Flac
|
||||
AddCategoryMapping(42, TorznabCatType.AudioOther); // AUDIO/Soundtracks
|
||||
AddCategoryMapping(58, TorznabCatType.AudioVideo); // AUDIO/Musikvideos
|
||||
AddCategoryMapping(14, TorznabCatType.Audio); // AUDIO/Musik
|
||||
AddCategoryMapping(15, TorznabCatType.AudioAudiobook); // AUDIO/Hörbücher
|
||||
AddCategoryMapping(16, TorznabCatType.AudioAudiobook); // AUDIO/Hörspiele
|
||||
AddCategoryMapping(36, TorznabCatType.AudioLossless); // AUDIO/Flac
|
||||
AddCategoryMapping(42, TorznabCatType.AudioOther); // AUDIO/Soundtracks
|
||||
AddCategoryMapping(58, TorznabCatType.AudioVideo); // AUDIO/Musikvideos
|
||||
|
||||
AddCategoryMapping(18, TorznabCatType.TVSD); // TV/Serien SD
|
||||
AddCategoryMapping(19, TorznabCatType.TVHD); // TV/Serien HD 720p
|
||||
AddCategoryMapping(20, TorznabCatType.TVHD); // TV/Serien HD 1080p
|
||||
AddCategoryMapping(49, TorznabCatType.TVSD); // TV/Serien DVD
|
||||
AddCategoryMapping(51, TorznabCatType.TVDocumentary); // TV/Doku SD
|
||||
AddCategoryMapping(52, TorznabCatType.TVDocumentary); // TV/Doku HD
|
||||
AddCategoryMapping(53, TorznabCatType.TV); // TV/Serien Complete Packs
|
||||
AddCategoryMapping(54, TorznabCatType.TVSport); // TV/Sport
|
||||
AddCategoryMapping(66, TorznabCatType.TVFOREIGN); // TV/International
|
||||
|
||||
AddCategoryMapping(22, TorznabCatType.Books); // MISC/EBooks
|
||||
AddCategoryMapping(24, TorznabCatType.Other); // MISC/Sonstiges
|
||||
AddCategoryMapping(25, TorznabCatType.Other); // MISC/Tonspuren
|
||||
AddCategoryMapping(18, TorznabCatType.TVSD); // TV/Serien SD
|
||||
AddCategoryMapping(19, TorznabCatType.TVHD); // TV/Serien HD 720p
|
||||
AddCategoryMapping(20, TorznabCatType.TVHD); // TV/Serien HD 1080p
|
||||
AddCategoryMapping(49, TorznabCatType.TVSD); // TV/Serien DVD
|
||||
AddCategoryMapping(51, TorznabCatType.TVDocumentary); // TV/Doku SD
|
||||
AddCategoryMapping(52, TorznabCatType.TVDocumentary); // TV/Doku HD
|
||||
AddCategoryMapping(53, TorznabCatType.TV); // TV/Serien Complete Packs
|
||||
AddCategoryMapping(54, TorznabCatType.TVSport); // TV/Sport
|
||||
AddCategoryMapping(66, TorznabCatType.TVFOREIGN); // TV/International
|
||||
|
||||
AddCategoryMapping(22, TorznabCatType.Books); // MISC/EBooks
|
||||
AddCategoryMapping(24, TorznabCatType.Other); // MISC/Sonstiges
|
||||
AddCategoryMapping(25, TorznabCatType.Other); // MISC/Tonspuren
|
||||
AddCategoryMapping(108, TorznabCatType.TVAnime); // MISC/Anime
|
||||
|
||||
AddCategoryMapping(28, TorznabCatType.PC); // APPLICATIONS/PC
|
||||
AddCategoryMapping(29, TorznabCatType.PCPhoneOther); // APPLICATIONS/Mobile
|
||||
AddCategoryMapping(30, TorznabCatType.PC); // APPLICATIONS/Sonstige
|
||||
AddCategoryMapping(70, TorznabCatType.PC); // APPLICATIONS/Linux
|
||||
AddCategoryMapping(71, TorznabCatType.PCMac); // APPLICATIONS/Mac
|
||||
}
|
||||
AddCategoryMapping(28, TorznabCatType.PC); // APPLICATIONS/PC
|
||||
AddCategoryMapping(29, TorznabCatType.PCPhoneOther); // APPLICATIONS/Mobile
|
||||
AddCategoryMapping(30, TorznabCatType.PC); // APPLICATIONS/Sonstige
|
||||
AddCategoryMapping(70, TorznabCatType.PC); // APPLICATIONS/Linux
|
||||
AddCategoryMapping(71, TorznabCatType.PCMac); // APPLICATIONS/Mac
|
||||
|
||||
public override void LoadValuesFromJson(JToken jsonConfig, bool useProtectionService = false)
|
||||
{
|
||||
base.LoadValuesFromJson(jsonConfig, useProtectionService);
|
||||
|
||||
// add self signed cert to trusted certs
|
||||
webclient.AddTrustedCertificate(new Uri(SiteLink).Host, certificateHash);
|
||||
}
|
||||
|
||||
|
@ -105,7 +99,8 @@ namespace Jackett.Indexers
|
|||
var loginPage = await RequestStringWithCookies(IndexUrl, string.Empty);
|
||||
CQ dom = loginPage.Content;
|
||||
CQ qCaptchaImg = dom.Find("td.tablea > img").First();
|
||||
if(qCaptchaImg.Length == 1) {
|
||||
if (qCaptchaImg.Length == 1)
|
||||
{
|
||||
var CaptchaUrl = SiteLink + qCaptchaImg.Attr("src");
|
||||
var captchaImage = await RequestBytesWithCookies(CaptchaUrl, loginPage.Cookies);
|
||||
configData.CaptchaImage.Value = captchaImage.Content;
|
||||
|
@ -121,7 +116,7 @@ namespace Jackett.Indexers
|
|||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
LoadValuesFromJson(configJson);
|
||||
|
||||
|
||||
var pairs = new Dictionary<string, string>
|
||||
{
|
||||
{ "strWebAction", "login" },
|
||||
|
@ -142,7 +137,7 @@ namespace Jackett.Indexers
|
|||
{
|
||||
CQ dom = result.Content;
|
||||
var errorMessage = dom["table > tbody > tr > td[valign=top][width=100%]"].Html();
|
||||
if(errorMessage.Length == 0)
|
||||
if (errorMessage.Length == 0)
|
||||
errorMessage = result.Content;
|
||||
throw new ExceptionWithConfigData(errorMessage, configData);
|
||||
}
|
||||
|
@ -166,7 +161,7 @@ namespace Jackett.Indexers
|
|||
TimeZoneInfo germanyTz = TimeZoneInfo.CreateCustomTimeZone("W. Europe Standard Time", new TimeSpan(1, 0, 0), "(GMT+01:00) W. Europe Standard Time", "W. Europe Standard Time", "W. Europe DST Time", adjustments);
|
||||
|
||||
var releases = new List<ReleaseInfo>();
|
||||
|
||||
|
||||
var searchString = query.GetQueryString();
|
||||
var searchUrl = IndexUrl;
|
||||
var queryCollection = new NameValueCollection();
|
||||
|
@ -236,7 +231,7 @@ namespace Jackett.Indexers
|
|||
else if (dateStrParts[0] == "Gestern")
|
||||
dateGerman = DateTime.SpecifyKind(DateTime.UtcNow.Date, DateTimeKind.Unspecified) + TimeSpan.Parse(dateStrParts[1]) - TimeSpan.FromDays(1);
|
||||
else
|
||||
dateGerman = DateTime.SpecifyKind(DateTime.ParseExact(dateStrParts[0]+ dateStrParts[1], "dd.MM.yyyyHH:mm", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
|
||||
dateGerman = DateTime.SpecifyKind(DateTime.ParseExact(dateStrParts[0] + dateStrParts[1], "dd.MM.yyyyHH:mm", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
|
||||
|
||||
DateTime pubDateUtc = TimeZoneInfo.ConvertTimeToUtc(dateGerman, germanyTz);
|
||||
release.PublishDate = pubDateUtc.ToLocalTime();
|
||||
|
|
|
@ -18,7 +18,7 @@ using Jackett.Models.IndexerConfig;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class TorrentLeech : BaseIndexer
|
||||
public class TorrentLeech : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "user/account/login/"; } }
|
||||
private string SearchUrl { get { return SiteLink + "torrents/browse/index/"; } }
|
||||
|
@ -29,12 +29,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public TorrentLeech(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
|
||||
public TorrentLeech(IIndexerConfigurationService configService, Logger l, IWebClient wc, IProtectionService ps)
|
||||
: base(name: "TorrentLeech",
|
||||
description: "This is what happens when you seed",
|
||||
link: "https://www.torrentleech.org/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -15,7 +15,7 @@ using System.Text;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class TorrentNetwork : BaseIndexer
|
||||
public class TorrentNetwork : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
string BrowseUrl { get { return SiteLink + "browse.php"; } }
|
||||
|
@ -26,12 +26,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public TorrentNetwork(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public TorrentNetwork(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "Torrent Network",
|
||||
description: "A German general tracker.",
|
||||
link: "https://tntracker.org/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -17,7 +17,7 @@ using System.Text.RegularExpressions;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class TorrentSyndikat : BaseIndexer
|
||||
public class TorrentSyndikat : BaseWebIndexer
|
||||
{
|
||||
private string SearchUrl { get { return SiteLink + "browse.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "eing2.php"; } }
|
||||
|
@ -30,12 +30,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public TorrentSyndikat(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public TorrentSyndikat(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "Torrent-Syndikat",
|
||||
description: "A German general tracker",
|
||||
link: "https://torrent-syndikat.org/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -18,7 +18,7 @@ using System.Web;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class Torrentech : BaseIndexer
|
||||
public class Torrentech : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "index.php?act=Login&CODE=01&CookieDate=1"; } }
|
||||
string IndexUrl { get { return SiteLink + "index.php"; } }
|
||||
|
@ -29,12 +29,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Torrentech(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public Torrentech(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "Torrentech",
|
||||
description: null,
|
||||
link: "https://www.torrentech.org/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -16,7 +16,7 @@ using System.Text.RegularExpressions;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class TransmitheNet : BaseIndexer
|
||||
public class TransmitheNet : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "torrents.php?action=basic&order_by=time&order_way=desc&search_type=0&taglist=&tags_type=0"; } }
|
||||
|
@ -27,12 +27,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public TransmitheNet(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps)
|
||||
public TransmitheNet(IIndexerConfigurationService configService, Logger l, IWebClient c, IProtectionService ps)
|
||||
: base(name: "Nebulance",
|
||||
description: " At Nebulance we will change the way you think about TV",
|
||||
link: "https://nebulance.io/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: c,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -19,7 +19,7 @@ using Jackett.Models.IndexerConfig;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class Trezzor : BaseIndexer
|
||||
public class Trezzor : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "prihlasenie.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "torrents.php?"; } }
|
||||
|
@ -31,12 +31,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Trezzor(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public Trezzor(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "Trezzor",
|
||||
description: "SK/CZ Tracker.",
|
||||
link: "https://tracker.czech-server.com/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Jackett.Indexers
|
|||
/// <summary>
|
||||
/// Provider for WiHD Private French Tracker
|
||||
/// </summary>
|
||||
public class WiHD : BaseIndexer
|
||||
public class WiHD : BaseCachingWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login"; } }
|
||||
private string LoginCheckUrl { get { return SiteLink + "login_check"; } }
|
||||
|
@ -40,13 +40,13 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public WiHD(IIndexerManagerService i, IWebClient w, Logger l, IProtectionService ps)
|
||||
public WiHD(IIndexerConfigurationService configService, IWebClient w, Logger l, IProtectionService ps)
|
||||
: base(
|
||||
name: "WiHD",
|
||||
description: "Your World in High Definition",
|
||||
link: "http://world-in-hd.net/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
@ -110,7 +110,8 @@ namespace Jackett.Indexers
|
|||
// emulatedBrowserHeaders.Add("Accept-Encoding", "gzip, deflate");
|
||||
|
||||
// If we want to simulate a browser
|
||||
if (ConfigData.Browser.Value) {
|
||||
if (ConfigData.Browser.Value)
|
||||
{
|
||||
|
||||
// Clean headers
|
||||
emulatedBrowserHeaders.Clear();
|
||||
|
@ -150,7 +151,8 @@ namespace Jackett.Indexers
|
|||
};
|
||||
|
||||
// Do the login
|
||||
var request = new Utils.Clients.WebRequest(){
|
||||
var request = new Utils.Clients.WebRequest()
|
||||
{
|
||||
Cookies = loginPage.Cookies,
|
||||
PostData = pairs,
|
||||
Referer = LoginUrl,
|
||||
|
@ -165,7 +167,7 @@ namespace Jackett.Indexers
|
|||
var response = await RequestLoginAndFollowRedirect(LoginCheckUrl, pairs, loginPage.Cookies, true, null, null);
|
||||
|
||||
// Test if we are logged in
|
||||
await ConfigureIfOK(response.Cookies, response.Content != null && response.Content.Contains("/logout"), () =>
|
||||
await ConfigureIfOK(response.Cookies, response.Content != null && response.Content.Contains("/logout"), () =>
|
||||
{
|
||||
// Oops, unable to login
|
||||
output("-> Login failed", "error");
|
||||
|
@ -236,7 +238,8 @@ namespace Jackett.Indexers
|
|||
// Calculate numbers of pages available for this search query (Based on number results and number of torrents on first page)
|
||||
pageLinkCount = (int)Math.Ceiling((double)nbResults / firstPageRows.Length);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// Check if we have a minimum of one result
|
||||
if (firstPageRows.Length >= 1)
|
||||
{
|
||||
|
@ -416,7 +419,7 @@ namespace Jackett.Indexers
|
|||
foreach (string category in categoriesList)
|
||||
{
|
||||
// If last, build !
|
||||
if(categoriesList.Last() == category)
|
||||
if (categoriesList.Last() == category)
|
||||
{
|
||||
// Adding previous categories to URL with latest category
|
||||
parameters.Add(Uri.EscapeDataString("subcat[]"), category + categories);
|
||||
|
@ -557,7 +560,8 @@ namespace Jackett.Indexers
|
|||
.Select(f => new System.IO.FileInfo(f))
|
||||
.Where(f => f.LastAccessTime < DateTime.Now.AddMilliseconds(-Convert.ToInt32(ConfigData.HardDriveCacheKeepTime.Value)))
|
||||
.ToList()
|
||||
.ForEach(f => {
|
||||
.ForEach(f =>
|
||||
{
|
||||
output("Deleting cached file << " + f.Name + " >> ... done.");
|
||||
f.Delete();
|
||||
i++;
|
||||
|
@ -568,7 +572,8 @@ namespace Jackett.Indexers
|
|||
{
|
||||
output("-> Deleted " + i + " cached files during cleaning.");
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
output("-> Nothing deleted during cleaning.");
|
||||
}
|
||||
}
|
||||
|
@ -580,7 +585,7 @@ namespace Jackett.Indexers
|
|||
private void latencyNow()
|
||||
{
|
||||
// Need latency ?
|
||||
if(Latency)
|
||||
if (Latency)
|
||||
{
|
||||
// Generate a random value in our range
|
||||
var random = new Random(DateTime.Now.Millisecond);
|
||||
|
@ -620,10 +625,10 @@ namespace Jackett.Indexers
|
|||
private DateTime agoToDate(IList<string> clockList)
|
||||
{
|
||||
DateTime release = DateTime.Now;
|
||||
foreach(var ago in clockList)
|
||||
foreach (var ago in clockList)
|
||||
{
|
||||
// Check for years
|
||||
if(ago.Contains("Années") || ago.Contains("Année"))
|
||||
if (ago.Contains("Années") || ago.Contains("Année"))
|
||||
{
|
||||
// Number of years to remove
|
||||
int years = ParseUtil.CoerceInt(Regex.Match(ago.ToString(), @"\d+").Value);
|
||||
|
@ -737,7 +742,7 @@ namespace Jackett.Indexers
|
|||
if (dictionary.ContainsKey(media))
|
||||
{
|
||||
// Due to a bug on tracker side, check for a specific id/name as image is same for TV/Anime BR 3D
|
||||
if(media == "565af82d1fd35761568b4592" && name == "Animations - Bluray 3D")
|
||||
if (media == "565af82d1fd35761568b4592" && name == "Animations - Bluray 3D")
|
||||
{
|
||||
// If it's an Anime BR 3D
|
||||
return "565af82d1fd35761568b45a6";
|
||||
|
@ -763,7 +768,7 @@ namespace Jackett.Indexers
|
|||
private void output(string message, string level = "debug")
|
||||
{
|
||||
// Check if we are in dev mode
|
||||
if(DevMode)
|
||||
if (DevMode)
|
||||
{
|
||||
// Output message to console
|
||||
Console.WriteLine(message);
|
||||
|
@ -777,7 +782,7 @@ namespace Jackett.Indexers
|
|||
goto case "debug";
|
||||
case "debug":
|
||||
// Only if Debug Level Enabled on Jackett
|
||||
if(Engine.Logger.IsDebugEnabled)
|
||||
if (Engine.Logger.IsDebugEnabled)
|
||||
{
|
||||
logger.Debug(message);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ using static Jackett.Models.IndexerConfig.ConfigurationData;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class XSpeeds : BaseIndexer
|
||||
public class XSpeeds : BaseWebIndexer
|
||||
{
|
||||
string LandingUrl => SiteLink + "login.php";
|
||||
string LoginUrl => SiteLink + "takelogin.php";
|
||||
|
@ -35,12 +35,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public XSpeeds(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public XSpeeds(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "XSpeeds",
|
||||
description: "XSpeeds",
|
||||
link: "https://www.xspeeds.eu/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Jackett.Indexers
|
|||
/// <summary>
|
||||
/// Provider for Xthor Private French Tracker
|
||||
/// </summary>
|
||||
public class Xthor : BaseIndexer
|
||||
public class Xthor : BaseCachingWebIndexer
|
||||
{
|
||||
private static string ApiEndpoint => "https://api.xthor.bz/";
|
||||
private string TorrentCommentUrl => TorrentDescriptionUrl;
|
||||
|
@ -31,13 +31,13 @@ namespace Jackett.Indexers
|
|||
public Dictionary<string, string> EmulatedBrowserHeaders { get; } = new Dictionary<string, string>();
|
||||
private ConfigurationDataXthor ConfigData => (ConfigurationDataXthor)configData;
|
||||
|
||||
public Xthor(IIndexerManagerService i, IWebClient w, Logger l, IProtectionService ps)
|
||||
public Xthor(IIndexerConfigurationService configService, IWebClient w, Logger l, IProtectionService ps)
|
||||
: base(
|
||||
name: "Xthor",
|
||||
description: "General French Private Tracker",
|
||||
link: "https://xthor.bz/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
@ -115,9 +115,9 @@ namespace Jackett.Indexers
|
|||
/// </summary>
|
||||
/// <param name="configJson">Our params in Json</param>
|
||||
/// <returns>Configuration state</returns>
|
||||
#pragma warning disable 1998
|
||||
#pragma warning disable 1998
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
#pragma warning restore 1998
|
||||
#pragma warning restore 1998
|
||||
{
|
||||
// Provider not yet configured
|
||||
IsConfigured = false;
|
||||
|
@ -159,7 +159,7 @@ namespace Jackett.Indexers
|
|||
var searchTerm = query.GetQueryString();
|
||||
|
||||
// Check cache first so we don't query the server (if search term used or not in dev mode)
|
||||
if(!DevMode && !string.IsNullOrEmpty(searchTerm))
|
||||
if (!DevMode && !string.IsNullOrEmpty(searchTerm))
|
||||
{
|
||||
lock (cache)
|
||||
{
|
||||
|
@ -195,7 +195,8 @@ namespace Jackett.Indexers
|
|||
{
|
||||
// Mapping data
|
||||
Category = MapTrackerCatToNewznab(torrent.category.ToString()),
|
||||
Title = torrent.name, Seeders = torrent.seeders,
|
||||
Title = torrent.name,
|
||||
Seeders = torrent.seeders,
|
||||
Peers = torrent.seeders + torrent.leechers,
|
||||
MinimumRatio = 1,
|
||||
MinimumSeedTime = 345600,
|
||||
|
@ -453,13 +454,13 @@ namespace Jackett.Indexers
|
|||
private void CleanCacheStorage(bool force = false)
|
||||
{
|
||||
// Check cleaning method
|
||||
if(force)
|
||||
if (force)
|
||||
{
|
||||
// Deleting Provider Storage folder and all files recursively
|
||||
Output("\nDeleting Provider Storage folder and all files recursively ...");
|
||||
|
||||
|
||||
// Check if directory exist
|
||||
if(System.IO.Directory.Exists(Directory))
|
||||
if (System.IO.Directory.Exists(Directory))
|
||||
{
|
||||
// Delete storage directory of provider
|
||||
System.IO.Directory.Delete(Directory, true);
|
||||
|
@ -480,17 +481,20 @@ namespace Jackett.Indexers
|
|||
.Select(f => new System.IO.FileInfo(f))
|
||||
.Where(f => f.LastAccessTime < DateTime.Now.AddMilliseconds(-Convert.ToInt32(ConfigData.HardDriveCacheKeepTime.Value)))
|
||||
.ToList()
|
||||
.ForEach(f => {
|
||||
.ForEach(f =>
|
||||
{
|
||||
Output("Deleting cached file << " + f.Name + " >> ... done.");
|
||||
f.Delete();
|
||||
i++;
|
||||
});
|
||||
});
|
||||
|
||||
// Inform on what was cleaned during process
|
||||
if(i > 0) {
|
||||
if (i > 0)
|
||||
{
|
||||
Output("-> Deleted " + i + " cached files during cleaning.");
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
Output("-> Nothing deleted during cleaning.");
|
||||
}
|
||||
}
|
||||
|
@ -504,7 +508,7 @@ namespace Jackett.Indexers
|
|||
private void Output(string message, string level = "debug")
|
||||
{
|
||||
// Check if we are in dev mode
|
||||
if(DevMode)
|
||||
if (DevMode)
|
||||
{
|
||||
// Output message to console
|
||||
Console.WriteLine(message);
|
||||
|
|
|
@ -8,11 +8,11 @@ namespace Jackett.Indexers
|
|||
{
|
||||
public class CGPeers : GazelleTracker
|
||||
{
|
||||
public CGPeers(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
public CGPeers(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
: base(name: "CGPeers",
|
||||
desc: null,
|
||||
link: "https://www.cgpeers.com/",
|
||||
indexerManager: indexerManager,
|
||||
configService: configService,
|
||||
logger: logger,
|
||||
protectionService: protectionService,
|
||||
webClient: webClient
|
||||
|
|
|
@ -15,7 +15,7 @@ using System.Text;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class myAmity : BaseIndexer
|
||||
public class myAmity : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "account-login.php"; } }
|
||||
string BrowseUrl { get { return SiteLink + "torrents-search.php"; } }
|
||||
|
@ -26,12 +26,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public myAmity(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public myAmity(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "myAmity",
|
||||
description: "A German general tracker.",
|
||||
link: "https://ttv2.myamity.info/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -8,11 +8,11 @@ namespace Jackett.Indexers
|
|||
{
|
||||
public class notwhatcd : GazelleTracker
|
||||
{
|
||||
public notwhatcd(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
public notwhatcd(IIndexerConfigurationService configService, IWebClient webClient, Logger logger, IProtectionService protectionService)
|
||||
: base(name: "notwhat.cd",
|
||||
desc: "A music tracker",
|
||||
link: "https://notwhat.cd/",
|
||||
indexerManager: indexerManager,
|
||||
configService: configService,
|
||||
logger: logger,
|
||||
protectionService: protectionService,
|
||||
webClient: webClient
|
||||
|
|
|
@ -14,7 +14,7 @@ using AngleSharp.Parser.Html;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class RuTracker : BaseIndexer
|
||||
public class RuTracker : BaseWebIndexer
|
||||
{
|
||||
string LoginUrl { get { return SiteLink + "forum/login.php"; } }
|
||||
string SearchUrl { get { return SiteLink + "forum/tracker.php"; } }
|
||||
|
@ -28,12 +28,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public RuTracker(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
|
||||
public RuTracker(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "RuTracker",
|
||||
description: null,
|
||||
link: "https://rutracker.org/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -15,7 +15,7 @@ using System.Collections.Specialized;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class x264 : BaseIndexer
|
||||
public class x264 : BaseWebIndexer
|
||||
{
|
||||
private string SearchUrl { get { return SiteLink + "browse.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
|
@ -27,12 +27,12 @@ namespace Jackett.Indexers
|
|||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public x264(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||
public x264(IIndexerConfigurationService configService, Logger l, IWebClient w, IProtectionService ps)
|
||||
: base(name: "x264",
|
||||
description: "A movie/TV tracker",
|
||||
link: "https://x264.me/",
|
||||
caps: new TorznabCapabilities(),
|
||||
manager: i,
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
|
|
|
@ -377,6 +377,8 @@
|
|||
<Compile Include="Indexers\Meta\ResultFilters.cs" />
|
||||
<Compile Include="Services\ImdbResolver.cs" />
|
||||
<Compile Include="Utils\Extensions.cs" />
|
||||
<Compile Include="Services\IndexerConfigurationService.cs" />
|
||||
<Compile Include="Models\IndexerDefinition.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config">
|
||||
|
@ -573,8 +575,10 @@
|
|||
<MonoDevelop>
|
||||
<Properties>
|
||||
<Policies>
|
||||
<TextStylePolicy inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
|
||||
<CSharpFormattingPolicy IndentSwitchBody="True" IndentBlocksInsideExpressions="True" AnonymousMethodBraceStyle="NextLine" PropertyBraceStyle="NextLine" PropertyGetBraceStyle="NextLine" PropertySetBraceStyle="NextLine" EventBraceStyle="NextLine" EventAddBraceStyle="NextLine" EventRemoveBraceStyle="NextLine" StatementBraceStyle="NextLine" ElseNewLinePlacement="NewLine" CatchNewLinePlacement="NewLine" FinallyNewLinePlacement="NewLine" WhileNewLinePlacement="DoNotCare" ArrayInitializerWrapping="DoNotChange" ArrayInitializerBraceStyle="NextLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
|
||||
<TextStylePolicy TabWidth="4" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" FileWidth="80" TabsToSpaces="True" scope="text/plain">
|
||||
<inheritsSet />
|
||||
<inheritsScope />
|
||||
</TextStylePolicy>
|
||||
</Policies>
|
||||
</Properties>
|
||||
</MonoDevelop>
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Jackett.Models
|
||||
{
|
||||
// A Dictionary allowing the same key multiple times
|
||||
public class KeyValuePairList : List<KeyValuePair<string, selectorBlock>>, IDictionary<string, selectorBlock>
|
||||
{
|
||||
public selectorBlock this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
base.Add(new KeyValuePair<string, selectorBlock>(key, value));
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<string> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<selectorBlock> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(string key, selectorBlock value)
|
||||
{
|
||||
base.Add(new KeyValuePair<string, selectorBlock>(key, value));
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out selectorBlock value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
// Cardigann yaml classes
|
||||
public class IndexerDefinition
|
||||
{
|
||||
public string Site { get; set; }
|
||||
public List<settingsField> Settings { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Language { get; set; }
|
||||
public string Encoding { get; set; }
|
||||
public List<string> Links { get; set; }
|
||||
public List<string> Certificates { get; set; }
|
||||
public capabilitiesBlock Caps { get; set; }
|
||||
public loginBlock Login { get; set; }
|
||||
public ratioBlock Ratio { get; set; }
|
||||
public searchBlock Search { get; set; }
|
||||
public downloadBlock Download { get; set; }
|
||||
// IndexerDefinitionStats not needed/implemented
|
||||
}
|
||||
public class settingsField
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Label { get; set; }
|
||||
public string Default { get; set; }
|
||||
public Dictionary<string, string> Options { get; set; }
|
||||
}
|
||||
|
||||
public class CategorymappingBlock
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string cat { get; set; }
|
||||
public string desc { get; set; }
|
||||
}
|
||||
|
||||
public class capabilitiesBlock
|
||||
{
|
||||
public Dictionary<string, string> Categories { get; set; }
|
||||
public List<CategorymappingBlock> Categorymappings { get; set; }
|
||||
public Dictionary<string, List<string>> Modes { get; set; }
|
||||
}
|
||||
|
||||
public class captchaBlock
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public string Image { get; set; }
|
||||
public string Input { get; set; }
|
||||
}
|
||||
|
||||
public class loginBlock
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string Submitpath { get; set; }
|
||||
public List<string> Cookies { get; set; }
|
||||
public string Method { get; set; }
|
||||
public string Form { get; set; }
|
||||
public bool Selectors { get; set; } = false;
|
||||
public Dictionary<string, string> Inputs { get; set; }
|
||||
public Dictionary<string, selectorBlock> Selectorinputs { get; set; }
|
||||
public Dictionary<string, selectorBlock> Getselectorinputs { get; set; }
|
||||
public List<errorBlock> Error { get; set; }
|
||||
public pageTestBlock Test { get; set; }
|
||||
public captchaBlock Captcha { get; set; }
|
||||
}
|
||||
|
||||
public class errorBlock
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string Selector { get; set; }
|
||||
public selectorBlock Message { get; set; }
|
||||
}
|
||||
|
||||
public class selectorBlock
|
||||
{
|
||||
public string Selector { get; set; }
|
||||
public bool Optional { get; set; } = false;
|
||||
public string Text { get; set; }
|
||||
public string Attribute { get; set; }
|
||||
public string Remove { get; set; }
|
||||
public List<filterBlock> Filters { get; set; }
|
||||
public Dictionary<string, string> Case { get; set; }
|
||||
}
|
||||
|
||||
public class filterBlock
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public dynamic Args { get; set; }
|
||||
}
|
||||
|
||||
public class pageTestBlock
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string Selector { get; set; }
|
||||
}
|
||||
|
||||
public class ratioBlock : selectorBlock
|
||||
{
|
||||
public string Path { get; set; }
|
||||
}
|
||||
|
||||
public class searchBlock
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public List<searchPathBlock> Paths { get; set; }
|
||||
public Dictionary<string, List<string>> Headers { get; set; }
|
||||
public List<filterBlock> Keywordsfilters { get; set; }
|
||||
public Dictionary<string, string> Inputs { get; set; }
|
||||
public List<errorBlock> Error { get; set; }
|
||||
public rowsBlock Rows { get; set; }
|
||||
public KeyValuePairList Fields { get; set; }
|
||||
}
|
||||
|
||||
public class rowsBlock : selectorBlock
|
||||
{
|
||||
public int After { get; set; }
|
||||
//public string Remove { get; set; } // already inherited
|
||||
public selectorBlock Dateheaders { get; set; }
|
||||
}
|
||||
|
||||
public class searchPathBlock : requestBlock
|
||||
{
|
||||
public List<string> Categories { get; set; }
|
||||
public bool Inheritinputs { get; set; } = true;
|
||||
}
|
||||
|
||||
public class requestBlock
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string Method { get; set; }
|
||||
public Dictionary<string, string> Inputs { get; set; }
|
||||
}
|
||||
|
||||
public class downloadBlock
|
||||
{
|
||||
public string Selector { get; set; }
|
||||
public string Method { get; set; }
|
||||
public requestBlock Before { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Jackett.Indexers;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
|
||||
namespace Jackett.Services
|
||||
{
|
||||
public interface IIndexerConfigurationService
|
||||
{
|
||||
void Load(IIndexer indexer);
|
||||
void Save(IIndexer indexer, JToken config);
|
||||
void Delete(IIndexer indexer);
|
||||
}
|
||||
|
||||
public class IndexerConfigurationService : IIndexerConfigurationService
|
||||
{
|
||||
|
||||
//public override void LoadFromSavedConfiguration(JToken jsonConfig)
|
||||
//{
|
||||
// if (jsonConfig is JObject)
|
||||
// {
|
||||
// configData.CookieHeader.Value = jsonConfig.Value<string>("cookies");
|
||||
// configData.IncludeRaw.Value = jsonConfig.Value<bool>("raws");
|
||||
// IsConfigured = true;
|
||||
// SaveConfig();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// base.LoadFromSavedConfiguration(jsonConfig);
|
||||
//}
|
||||
|
||||
public IndexerConfigurationService(IConfigurationService configService, Logger logger)
|
||||
{
|
||||
this.configService = configService;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public void Delete(IIndexer indexer)
|
||||
{
|
||||
var configFilePath = GetIndexerConfigFilePath(indexer);
|
||||
File.Delete(configFilePath);
|
||||
}
|
||||
|
||||
public void Load(IIndexer idx)
|
||||
{
|
||||
var configFilePath = GetIndexerConfigFilePath(idx);
|
||||
if (File.Exists(configFilePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
var fileStr = File.ReadAllText(configFilePath);
|
||||
var jsonString = JToken.Parse(fileStr);
|
||||
idx.LoadFromSavedConfiguration(jsonString);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "Failed loading configuration for {0}, trying backup", idx.DisplayName);
|
||||
var configFilePathBak = configFilePath + ".bak";
|
||||
if (File.Exists(configFilePathBak))
|
||||
{
|
||||
try
|
||||
{
|
||||
var fileStrBak = File.ReadAllText(configFilePathBak);
|
||||
var jsonStringBak = JToken.Parse(fileStrBak);
|
||||
idx.LoadFromSavedConfiguration(jsonStringBak);
|
||||
logger.Info("Successfully loaded backup config for {0}", idx.DisplayName);
|
||||
idx.SaveConfig();
|
||||
}
|
||||
catch (Exception exbak)
|
||||
{
|
||||
logger.Error(exbak, "Failed loading backup configuration for {0}, you must reconfigure this indexer", idx.DisplayName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Error(ex, "Failed loading backup configuration for {0} (no backup available), you must reconfigure this indexer", idx.DisplayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(IIndexer indexer, JToken obj)
|
||||
{
|
||||
lock (configWriteLock)
|
||||
{
|
||||
var uID = Guid.NewGuid().ToString("N");
|
||||
var configFilePath = GetIndexerConfigFilePath(indexer);
|
||||
var configFilePathBak = configFilePath + ".bak";
|
||||
var configFilePathTmp = configFilePath + "." + uID + ".tmp";
|
||||
var content = obj.ToString();
|
||||
|
||||
logger.Debug(string.Format("Saving new config file: {0}", configFilePathTmp));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(content))
|
||||
{
|
||||
throw new Exception(string.Format("New config content for {0} is empty, please report this bug.", indexer.ID));
|
||||
}
|
||||
|
||||
if (content.Contains("\x00"))
|
||||
{
|
||||
throw new Exception(string.Format("New config content for {0} contains 0x00, please report this bug. Content: {1}", indexer.ID, content));
|
||||
}
|
||||
|
||||
// make sure the config directory exists
|
||||
if (!Directory.Exists(configService.GetIndexerConfigDir()))
|
||||
Directory.CreateDirectory(configService.GetIndexerConfigDir());
|
||||
|
||||
// create new temporary config file
|
||||
File.WriteAllText(configFilePathTmp, content);
|
||||
var fileInfo = new FileInfo(configFilePathTmp);
|
||||
if (fileInfo.Length == 0)
|
||||
{
|
||||
throw new Exception(string.Format("New config file {0} is empty, please report this bug.", configFilePathTmp));
|
||||
}
|
||||
|
||||
// create backup file
|
||||
File.Delete(configFilePathBak);
|
||||
if (File.Exists(configFilePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Move(configFilePath, configFilePathBak);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.Error(string.Format("Error while moving {0} to {1}: {2}", configFilePath, configFilePathBak, ex.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
// replace the actual config file
|
||||
File.Delete(configFilePath);
|
||||
try
|
||||
{
|
||||
File.Move(configFilePathTmp, configFilePath);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.Error(string.Format("Error while moving {0} to {1}: {2}", configFilePathTmp, configFilePath, ex.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetIndexerConfigFilePath(IIndexer indexer)
|
||||
{
|
||||
return Path.Combine(configService.GetIndexerConfigDir(), indexer.ID + ".json");
|
||||
}
|
||||
|
||||
private IConfigurationService configService;
|
||||
private Logger logger;
|
||||
|
||||
private static readonly object configWriteLock = new object();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue