From 9e3076dde6e12f0f54a04a87c375940459aa265c Mon Sep 17 00:00:00 2001 From: chibidev Date: Mon, 10 Jul 2017 22:58:44 +0200 Subject: [PATCH] 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. --- src/CurlSharp/CurlSharp.csproj | 10 +- src/Jackett.sln | 13 +- src/Jackett/Controllers/AdminController.cs | 10 +- .../Controllers/BlackholeController.cs | 4 +- src/Jackett/Controllers/DownloadController.cs | 17 +- src/Jackett/Controllers/PotatoController.cs | 14 +- src/Jackett/Controllers/TorznabController.cs | 16 +- src/Jackett/Indexers/7tor.cs | 6 +- src/Jackett/Indexers/Abnormal.cs | 41 +- .../Indexers/Abstract/AvistazTracker.cs | 6 +- .../Indexers/Abstract/GazelleTracker.cs | 6 +- src/Jackett/Indexers/AlphaRatio.cs | 6 +- src/Jackett/Indexers/Andraste.cs | 6 +- src/Jackett/Indexers/AnimeBytes.cs | 31 +- src/Jackett/Indexers/AnimeTorrents.cs | 6 +- src/Jackett/Indexers/ArcheTorrent.cs | 6 +- src/Jackett/Indexers/Avistaz.cs | 4 +- src/Jackett/Indexers/BB.cs | 6 +- src/Jackett/Indexers/BJShare.cs | 6 +- src/Jackett/Indexers/BakaBT.cs | 6 +- src/Jackett/Indexers/BaseIndexer.cs | 565 ++++++++++-------- src/Jackett/Indexers/BestFriends.cs | 6 +- src/Jackett/Indexers/BeyondHD.cs | 6 +- src/Jackett/Indexers/BitCityReloaded.cs | 6 +- src/Jackett/Indexers/BitHdtv.cs | 6 +- src/Jackett/Indexers/BitMeTV.cs | 6 +- src/Jackett/Indexers/BitSoup.cs | 6 +- src/Jackett/Indexers/BroadcastTheNet.cs | 6 +- src/Jackett/Indexers/BrokenStones.cs | 4 +- src/Jackett/Indexers/CardigannIndexer.cs | 280 ++------- src/Jackett/Indexers/CinemaZ.cs | 4 +- src/Jackett/Indexers/DanishBits.cs | 8 +- src/Jackett/Indexers/Demonoid.cs | 6 +- src/Jackett/Indexers/DigitalHive.cs | 6 +- src/Jackett/Indexers/EliteTracker.cs | 6 +- src/Jackett/Indexers/FileList.cs | 6 +- src/Jackett/Indexers/FunFile.cs | 6 +- src/Jackett/Indexers/Fuzer.cs | 6 +- src/Jackett/Indexers/GFTracker.cs | 6 +- src/Jackett/Indexers/GhostCity.cs | 6 +- src/Jackett/Indexers/GimmePeers.cs | 8 +- src/Jackett/Indexers/HD4Free.cs | 6 +- src/Jackett/Indexers/HDForever.cs | 4 +- src/Jackett/Indexers/HDOnly.cs | 4 +- src/Jackett/Indexers/HDSpace.cs | 6 +- src/Jackett/Indexers/HDTorrents.cs | 6 +- src/Jackett/Indexers/Hardbay.cs | 8 +- src/Jackett/Indexers/Hebits.cs | 6 +- src/Jackett/Indexers/Hounddawgs.cs | 8 +- src/Jackett/Indexers/HouseOfTorrents.cs | 6 +- src/Jackett/Indexers/IIndexer.cs | 14 +- src/Jackett/Indexers/IPTorrents.cs | 6 +- src/Jackett/Indexers/ImmortalSeed.cs | 6 +- src/Jackett/Indexers/Meta/BaseMetaIndexer.cs | 64 +- src/Jackett/Indexers/Meta/MetaIndexers.cs | 4 +- src/Jackett/Indexers/MoreThanTV.cs | 6 +- src/Jackett/Indexers/MyAnonamouse.cs | 6 +- src/Jackett/Indexers/NCore.cs | 6 +- src/Jackett/Indexers/NewRealWorld.cs | 6 +- src/Jackett/Indexers/Norbits.cs | 22 +- src/Jackett/Indexers/PassThePopcorn.cs | 6 +- src/Jackett/Indexers/PiXELHD.cs | 6 +- src/Jackett/Indexers/PirateTheNet.cs | 6 +- src/Jackett/Indexers/Pretome.cs | 6 +- src/Jackett/Indexers/PrivateHD.cs | 4 +- src/Jackett/Indexers/Psytorrents.cs | 4 +- src/Jackett/Indexers/Rarbg.cs | 6 +- src/Jackett/Indexers/Redacted.cs | 4 +- src/Jackett/Indexers/RevolutionTT.cs | 6 +- src/Jackett/Indexers/SceneAccess.cs | 6 +- src/Jackett/Indexers/SceneFZ.cs | 6 +- src/Jackett/Indexers/SceneTime.cs | 6 +- src/Jackett/Indexers/Shazbat.cs | 6 +- src/Jackett/Indexers/ShowRSS.cs | 6 +- src/Jackett/Indexers/SpeedCD.cs | 8 +- src/Jackett/Indexers/Superbits.cs | 6 +- src/Jackett/Indexers/T411.cs | 8 +- src/Jackett/Indexers/TVChaosUK.cs | 6 +- src/Jackett/Indexers/TVVault.cs | 6 +- src/Jackett/Indexers/TehConnection.cs | 6 +- src/Jackett/Indexers/TorrentBytes.cs | 6 +- src/Jackett/Indexers/TorrentDay.cs | 6 +- src/Jackett/Indexers/TorrentHeaven.cs | 95 ++- src/Jackett/Indexers/TorrentLeech.cs | 6 +- src/Jackett/Indexers/TorrentNetwork.cs | 6 +- src/Jackett/Indexers/TorrentSyndikat.cs | 6 +- src/Jackett/Indexers/Torrentech.cs | 6 +- src/Jackett/Indexers/TransmitheNet.cs | 6 +- src/Jackett/Indexers/Trezzor.cs | 6 +- src/Jackett/Indexers/WiHD.cs | 37 +- src/Jackett/Indexers/XSpeeds.cs | 6 +- src/Jackett/Indexers/Xthor.cs | 34 +- src/Jackett/Indexers/cgpeers.cs | 4 +- src/Jackett/Indexers/myAmity.cs | 6 +- src/Jackett/Indexers/notwhatcd.cs | 4 +- src/Jackett/Indexers/rutracker.cs | 6 +- src/Jackett/Indexers/x264.cs | 6 +- src/Jackett/Jackett.csproj | 8 +- src/Jackett/Models/IndexerDefinition.cs | 197 ++++++ .../Services/IndexerConfigurationService.cs | 154 +++++ src/Jackett/Services/IndexerManagerService.cs | 164 +---- src/Jackett/Services/ServerService.cs | 13 +- src/Jackett/Utils/Extensions.cs | 13 + src/Jackett/Utils/StringUtil.cs | 4 +- 104 files changed, 1188 insertions(+), 1102 deletions(-) create mode 100644 src/Jackett/Models/IndexerDefinition.cs create mode 100644 src/Jackett/Services/IndexerConfigurationService.cs diff --git a/src/CurlSharp/CurlSharp.csproj b/src/CurlSharp/CurlSharp.csproj index a5676d902..7819e5ace 100644 --- a/src/CurlSharp/CurlSharp.csproj +++ b/src/CurlSharp/CurlSharp.csproj @@ -94,8 +94,14 @@ - - + + + + + + + + diff --git a/src/Jackett.sln b/src/Jackett.sln index 6654e8b27..8452eab09 100644 --- a/src/Jackett.sln +++ b/src/Jackett.sln @@ -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 diff --git a/src/Jackett/Controllers/AdminController.cs b/src/Jackett/Controllers/AdminController.cs index d102e302f..b1eaa996b 100644 --- a/src/Jackett/Controllers/AdminController.cs +++ b/src/Jackett/Controllers/AdminController.cs @@ -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) { diff --git a/src/Jackett/Controllers/BlackholeController.cs b/src/Jackett/Controllers/BlackholeController.cs index 24a90b227..19ff888ce 100644 --- a/src/Jackett/Controllers/BlackholeController.cs +++ b/src/Jackett/Controllers/BlackholeController.cs @@ -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)) diff --git a/src/Jackett/Controllers/DownloadController.cs b/src/Jackett/Controllers/DownloadController.cs index 05edde180..4d262c3b3 100644 --- a/src/Jackett/Controllers/DownloadController.cs +++ b/src/Jackett/Controllers/DownloadController.cs @@ -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 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 releases = new List(); 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(); diff --git a/src/Jackett/Controllers/TorznabController.cs b/src/Jackett/Controllers/TorznabController.cs index 6e9216228..a455d5afb 100644 --- a/src/Jackett/Controllers/TorznabController.cs +++ b/src/Jackett/Controllers/TorznabController.cs @@ -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()); } diff --git a/src/Jackett/Indexers/7tor.cs b/src/Jackett/Indexers/7tor.cs index 13318fdfe..b5106ab09 100644 --- a/src/Jackett/Indexers/7tor.cs +++ b/src/Jackett/Indexers/7tor.cs @@ -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, diff --git a/src/Jackett/Indexers/Abnormal.cs b/src/Jackett/Indexers/Abnormal.cs index 5316af586..517cfdc2c 100644 --- a/src/Jackett/Indexers/Abnormal.cs +++ b/src/Jackett/Indexers/Abnormal.cs @@ -22,7 +22,7 @@ namespace Jackett.Indexers /// /// Provider for Abnormal Private French Tracker /// - 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); diff --git a/src/Jackett/Indexers/Abstract/AvistazTracker.cs b/src/Jackett/Indexers/Abstract/AvistazTracker.cs index 444ed02ae..bdebc3529 100644 --- a/src/Jackett/Indexers/Abstract/AvistazTracker.cs +++ b/src/Jackett/Indexers/Abstract/AvistazTracker.cs @@ -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, diff --git a/src/Jackett/Indexers/Abstract/GazelleTracker.cs b/src/Jackett/Indexers/Abstract/GazelleTracker.cs index 182da75b2..8a58bc555 100644 --- a/src/Jackett/Indexers/Abstract/GazelleTracker.cs +++ b/src/Jackett/Indexers/Abstract/GazelleTracker.cs @@ -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, diff --git a/src/Jackett/Indexers/AlphaRatio.cs b/src/Jackett/Indexers/AlphaRatio.cs index c7dbe6c6f..e94b843a0 100644 --- a/src/Jackett/Indexers/AlphaRatio.cs +++ b/src/Jackett/Indexers/AlphaRatio.cs @@ -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, diff --git a/src/Jackett/Indexers/Andraste.cs b/src/Jackett/Indexers/Andraste.cs index f53739d5b..9856006b3 100644 --- a/src/Jackett/Indexers/Andraste.cs +++ b/src/Jackett/Indexers/Andraste.cs @@ -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, diff --git a/src/Jackett/Indexers/AnimeBytes.cs b/src/Jackett/Indexers/AnimeBytes.cs index dce491555..9d64eed1e 100644 --- a/src/Jackett/Indexers/AnimeBytes.cs +++ b/src/Jackett/Indexers/AnimeBytes.cs @@ -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 FilterResults(TorznabQuery query, IEnumerable input) + protected override IEnumerable FilterResults(TorznabQuery query, IEnumerable 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("cookies"); - configData.IncludeRaw.Value = jsonConfig.Value("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(); - + 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; } diff --git a/src/Jackett/Indexers/AnimeTorrents.cs b/src/Jackett/Indexers/AnimeTorrents.cs index e10529870..b88ca0a04 100644 --- a/src/Jackett/Indexers/AnimeTorrents.cs +++ b/src/Jackett/Indexers/AnimeTorrents.cs @@ -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, diff --git a/src/Jackett/Indexers/ArcheTorrent.cs b/src/Jackett/Indexers/ArcheTorrent.cs index 4d6328d65..231545845 100644 --- a/src/Jackett/Indexers/ArcheTorrent.cs +++ b/src/Jackett/Indexers/ArcheTorrent.cs @@ -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, diff --git a/src/Jackett/Indexers/Avistaz.cs b/src/Jackett/Indexers/Avistaz.cs index 6ae525fb0..50e77a172 100644 --- a/src/Jackett/Indexers/Avistaz.cs +++ b/src/Jackett/Indexers/Avistaz.cs @@ -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 diff --git a/src/Jackett/Indexers/BB.cs b/src/Jackett/Indexers/BB.cs index 8eab5eb35..83dc68586 100644 --- a/src/Jackett/Indexers/BB.cs +++ b/src/Jackett/Indexers/BB.cs @@ -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, diff --git a/src/Jackett/Indexers/BJShare.cs b/src/Jackett/Indexers/BJShare.cs index 8497e3af3..fc023a6ec 100644 --- a/src/Jackett/Indexers/BJShare.cs +++ b/src/Jackett/Indexers/BJShare.cs @@ -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, diff --git a/src/Jackett/Indexers/BakaBT.cs b/src/Jackett/Indexers/BakaBT.cs index 1f0713cd1..afbc6a727 100644 --- a/src/Jackett/Indexers/BakaBT.cs +++ b/src/Jackett/Indexers/BakaBT.cs @@ -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, diff --git a/src/Jackett/Indexers/BaseIndexer.cs b/src/Jackett/Indexers/BaseIndexer.cs index d39fa3b7d..03d2d2e12 100644 --- a/src/Jackett/Indexers/BaseIndexer.cs +++ b/src/Jackett/Indexers/BaseIndexer.cs @@ -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 cache = new List(); - 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 = new List(); + 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 CleanLinks(IEnumerable 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 MapTrackerCatToNewznab(string input) - { - var cats = new List(); - 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 MapTrackerCatDescToNewznab(string input) - { - var cats = new List(); - 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 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 cookieDIctionary = new Dictionary(); - 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 Download(Uri link) { - return await Download(link, RequestType.GET); + protected async Task ConfigureIfOK(string cookies, bool isLoggedin, Func onError) + { + if (isLoggedin) + { + CookieHeader = cookies; + IsConfigured = true; + SaveConfig(); + } + else + { + await onError(); + } + } + + protected virtual IEnumerable FilterResults(TorznabQuery query, IEnumerable 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 ApplyConfiguration(JToken configJson); + + public virtual async Task> 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> 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 Download(Uri link) + { + var uncleanLink = UncleanLink(link); + return await Download(uncleanLink, RequestType.GET); } protected async Task 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 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 FilterResults(TorznabQuery query, IEnumerable 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 cookieDIctionary = new Dictionary(); + 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 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(); + 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 ApplyConfiguration(JToken configJson); - - public virtual async Task> ResultsForQuery(TorznabQuery query) + protected ICollection MapTrackerCatDescToNewznab(string input) { - var results = await PerformQuery(query); - foreach (var result in results) + var cats = new List(); + 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 CleanLinks(IEnumerable 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> ResultsForQuery(TorznabQuery query) + { + var results = await base.ResultsForQuery(query); + results = CleanLinks(results); return results; } - protected abstract Task> 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 = new List(); + 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 cache = new List(); + protected static readonly TimeSpan cacheTime = new TimeSpan(0, 9, 0); } } diff --git a/src/Jackett/Indexers/BestFriends.cs b/src/Jackett/Indexers/BestFriends.cs index 096c1abbc..066101d46 100644 --- a/src/Jackett/Indexers/BestFriends.cs +++ b/src/Jackett/Indexers/BestFriends.cs @@ -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, diff --git a/src/Jackett/Indexers/BeyondHD.cs b/src/Jackett/Indexers/BeyondHD.cs index d12eb37d3..147a07a9e 100644 --- a/src/Jackett/Indexers/BeyondHD.cs +++ b/src/Jackett/Indexers/BeyondHD.cs @@ -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, diff --git a/src/Jackett/Indexers/BitCityReloaded.cs b/src/Jackett/Indexers/BitCityReloaded.cs index c67975de5..2d8e5ebd4 100644 --- a/src/Jackett/Indexers/BitCityReloaded.cs +++ b/src/Jackett/Indexers/BitCityReloaded.cs @@ -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, diff --git a/src/Jackett/Indexers/BitHdtv.cs b/src/Jackett/Indexers/BitHdtv.cs index 30baefccf..97176fb6b 100644 --- a/src/Jackett/Indexers/BitHdtv.cs +++ b/src/Jackett/Indexers/BitHdtv.cs @@ -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, diff --git a/src/Jackett/Indexers/BitMeTV.cs b/src/Jackett/Indexers/BitMeTV.cs index 641490276..5f6a07751 100644 --- a/src/Jackett/Indexers/BitMeTV.cs +++ b/src/Jackett/Indexers/BitMeTV.cs @@ -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, diff --git a/src/Jackett/Indexers/BitSoup.cs b/src/Jackett/Indexers/BitSoup.cs index 0440fb5ba..86ecf8960 100644 --- a/src/Jackett/Indexers/BitSoup.cs +++ b/src/Jackett/Indexers/BitSoup.cs @@ -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, diff --git a/src/Jackett/Indexers/BroadcastTheNet.cs b/src/Jackett/Indexers/BroadcastTheNet.cs index 9d8f42012..f8e358296 100644 --- a/src/Jackett/Indexers/BroadcastTheNet.cs +++ b/src/Jackett/Indexers/BroadcastTheNet.cs @@ -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, diff --git a/src/Jackett/Indexers/BrokenStones.cs b/src/Jackett/Indexers/BrokenStones.cs index f38b85dc8..2bf6bda00 100644 --- a/src/Jackett/Indexers/BrokenStones.cs +++ b/src/Jackett/Indexers/BrokenStones.cs @@ -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 diff --git a/src/Jackett/Indexers/CardigannIndexer.cs b/src/Jackett/Indexers/CardigannIndexer.cs index 5f8383857..b4939ce91 100644 --- a/src/Jackett/Indexers/CardigannIndexer.cs +++ b/src/Jackett/Indexers/CardigannIndexer.cs @@ -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>, IDictionary - { - public selectorBlock this[string key] - { - get - { - throw new NotImplementedException(); - } - - set - { - base.Add(new KeyValuePair(key, value)); - } - } - - public ICollection Keys - { - get - { - throw new NotImplementedException(); - } - } - - public ICollection Values - { - get - { - throw new NotImplementedException(); - } - } - - public void Add(string key, selectorBlock value) - { - base.Add(new KeyValuePair(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 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 Links { get; set; } - public List 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 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 Categories { get; set; } - public List Categorymappings { get; set; } - public Dictionary> 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 Cookies { get; set; } - public string Method { get; set; } - public string Form { get; set; } - public bool Selectors { get; set; } = false; - public Dictionary Inputs { get; set; } - public Dictionary Selectorinputs { get; set; } - public Dictionary Getselectorinputs { get; set; } - public List 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 Filters { get; set; } - public Dictionary 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 Paths { get; set; } - public Dictionary> Headers { get; set; } - public List Keywordsfilters { get; set; } - public Dictionary Inputs { get; set; } - public List 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 Categories { get; set; } - public bool Inheritinputs { get; set; } = true; - } - - public class requestBlock - { - public string Path { get; set; } - public string Method { get; set; } - public Dictionary 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(DefinitionString); + this.Definition = Definition; // Add default data if necessary if (Definition.Settings == null) - { + { Definition.Settings = new List(); 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 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) diff --git a/src/Jackett/Indexers/CinemaZ.cs b/src/Jackett/Indexers/CinemaZ.cs index 29f194b8f..563556cc4 100644 --- a/src/Jackett/Indexers/CinemaZ.cs +++ b/src/Jackett/Indexers/CinemaZ.cs @@ -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 diff --git a/src/Jackett/Indexers/DanishBits.cs b/src/Jackett/Indexers/DanishBits.cs index b743ef7cc..62ae2f217 100644 --- a/src/Jackett/Indexers/DanishBits.cs +++ b/src/Jackett/Indexers/DanishBits.cs @@ -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, diff --git a/src/Jackett/Indexers/Demonoid.cs b/src/Jackett/Indexers/Demonoid.cs index e0ae0bb2d..1eac98814 100644 --- a/src/Jackett/Indexers/Demonoid.cs +++ b/src/Jackett/Indexers/Demonoid.cs @@ -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, diff --git a/src/Jackett/Indexers/DigitalHive.cs b/src/Jackett/Indexers/DigitalHive.cs index afc7e7d63..8c76fa857 100644 --- a/src/Jackett/Indexers/DigitalHive.cs +++ b/src/Jackett/Indexers/DigitalHive.cs @@ -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, diff --git a/src/Jackett/Indexers/EliteTracker.cs b/src/Jackett/Indexers/EliteTracker.cs index 1568bcc1c..8fe749459 100644 --- a/src/Jackett/Indexers/EliteTracker.cs +++ b/src/Jackett/Indexers/EliteTracker.cs @@ -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, diff --git a/src/Jackett/Indexers/FileList.cs b/src/Jackett/Indexers/FileList.cs index 1d850cc38..cdc68c75c 100644 --- a/src/Jackett/Indexers/FileList.cs +++ b/src/Jackett/Indexers/FileList.cs @@ -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, diff --git a/src/Jackett/Indexers/FunFile.cs b/src/Jackett/Indexers/FunFile.cs index f8914f25a..4dd7730b5 100644 --- a/src/Jackett/Indexers/FunFile.cs +++ b/src/Jackett/Indexers/FunFile.cs @@ -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, diff --git a/src/Jackett/Indexers/Fuzer.cs b/src/Jackett/Indexers/Fuzer.cs index 3377c5d20..3d7f2834b 100644 --- a/src/Jackett/Indexers/Fuzer.cs +++ b/src/Jackett/Indexers/Fuzer.cs @@ -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, diff --git a/src/Jackett/Indexers/GFTracker.cs b/src/Jackett/Indexers/GFTracker.cs index c66db05ce..5f19effa4 100644 --- a/src/Jackett/Indexers/GFTracker.cs +++ b/src/Jackett/Indexers/GFTracker.cs @@ -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, diff --git a/src/Jackett/Indexers/GhostCity.cs b/src/Jackett/Indexers/GhostCity.cs index 202f9ceab..5b0f89f24 100644 --- a/src/Jackett/Indexers/GhostCity.cs +++ b/src/Jackett/Indexers/GhostCity.cs @@ -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, diff --git a/src/Jackett/Indexers/GimmePeers.cs b/src/Jackett/Indexers/GimmePeers.cs index 2e33faaa6..6c039dc0f 100644 --- a/src/Jackett/Indexers/GimmePeers.cs +++ b/src/Jackett/Indexers/GimmePeers.cs @@ -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, diff --git a/src/Jackett/Indexers/HD4Free.cs b/src/Jackett/Indexers/HD4Free.cs index 3b64a875d..e23428a4f 100644 --- a/src/Jackett/Indexers/HD4Free.cs +++ b/src/Jackett/Indexers/HD4Free.cs @@ -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, diff --git a/src/Jackett/Indexers/HDForever.cs b/src/Jackett/Indexers/HDForever.cs index b9b9e294b..214c8928e 100644 --- a/src/Jackett/Indexers/HDForever.cs +++ b/src/Jackett/Indexers/HDForever.cs @@ -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 diff --git a/src/Jackett/Indexers/HDOnly.cs b/src/Jackett/Indexers/HDOnly.cs index 437ebb239..2d866b5ad 100644 --- a/src/Jackett/Indexers/HDOnly.cs +++ b/src/Jackett/Indexers/HDOnly.cs @@ -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 diff --git a/src/Jackett/Indexers/HDSpace.cs b/src/Jackett/Indexers/HDSpace.cs index d50618435..162d14789 100644 --- a/src/Jackett/Indexers/HDSpace.cs +++ b/src/Jackett/Indexers/HDSpace.cs @@ -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, diff --git a/src/Jackett/Indexers/HDTorrents.cs b/src/Jackett/Indexers/HDTorrents.cs index 0939debe7..1e479ff7b 100644 --- a/src/Jackett/Indexers/HDTorrents.cs +++ b/src/Jackett/Indexers/HDTorrents.cs @@ -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, diff --git a/src/Jackett/Indexers/Hardbay.cs b/src/Jackett/Indexers/Hardbay.cs index 33536de3a..e2f37a167 100644 --- a/src/Jackett/Indexers/Hardbay.cs +++ b/src/Jackett/Indexers/Hardbay.cs @@ -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, diff --git a/src/Jackett/Indexers/Hebits.cs b/src/Jackett/Indexers/Hebits.cs index d1987b4ca..92ab4b415 100644 --- a/src/Jackett/Indexers/Hebits.cs +++ b/src/Jackett/Indexers/Hebits.cs @@ -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, diff --git a/src/Jackett/Indexers/Hounddawgs.cs b/src/Jackett/Indexers/Hounddawgs.cs index 6c022eee4..c6fcc0808 100644 --- a/src/Jackett/Indexers/Hounddawgs.cs +++ b/src/Jackett/Indexers/Hounddawgs.cs @@ -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, diff --git a/src/Jackett/Indexers/HouseOfTorrents.cs b/src/Jackett/Indexers/HouseOfTorrents.cs index 5e9d67a6f..861622e7c 100644 --- a/src/Jackett/Indexers/HouseOfTorrents.cs +++ b/src/Jackett/Indexers/HouseOfTorrents.cs @@ -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, diff --git a/src/Jackett/Indexers/IIndexer.cs b/src/Jackett/Indexers/IIndexer.cs index 1f9cafd77..5ff4174d6 100644 --- a/src/Jackett/Indexers/IIndexer.cs +++ b/src/Jackett/Indexers/IIndexer.cs @@ -37,15 +37,15 @@ namespace Jackett.Indexers void LoadFromSavedConfiguration(JToken jsonConfig); void SaveConfig(); + void Unconfigure(); + Task> ResultsForQuery(TorznabQuery query); - IEnumerable FilterResults(TorznabQuery query, IEnumerable input); - - Task Download(Uri link); - - IEnumerable CleanLinks(IEnumerable releases); - Uri UncleanLink(Uri link); - bool CanHandleQuery(TorznabQuery query); } + + public interface IWebIndexer : IIndexer + { + Task Download(Uri link); + } } diff --git a/src/Jackett/Indexers/IPTorrents.cs b/src/Jackett/Indexers/IPTorrents.cs index fb3bff0f3..076b1393e 100644 --- a/src/Jackett/Indexers/IPTorrents.cs +++ b/src/Jackett/Indexers/IPTorrents.cs @@ -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, diff --git a/src/Jackett/Indexers/ImmortalSeed.cs b/src/Jackett/Indexers/ImmortalSeed.cs index fc79fd85a..62e8e25ca 100644 --- a/src/Jackett/Indexers/ImmortalSeed.cs +++ b/src/Jackett/Indexers/ImmortalSeed.cs @@ -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, diff --git a/src/Jackett/Indexers/Meta/BaseMetaIndexer.cs b/src/Jackett/Indexers/Meta/BaseMetaIndexer.cs index 78f64acaa..a03f510b8 100644 --- a/src/Jackett/Indexers/Meta/BaseMetaIndexer.cs +++ b/src/Jackett/Indexers/Meta/BaseMetaIndexer.cs @@ -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 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 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> PerformQuery(TorznabQuery query) { - IEnumerable>> 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>> 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 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 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 Indexers; + private Func filterFunc; - private IEnumerable indexers; - public IEnumerable 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; } diff --git a/src/Jackett/Indexers/Meta/MetaIndexers.cs b/src/Jackett/Indexers/Meta/MetaIndexers.cs index db41953ab..9ab13631a 100644 --- a/src/Jackett/Indexers/Meta/MetaIndexers.cs +++ b/src/Jackett/Indexers/Meta/MetaIndexers.cs @@ -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) { } } diff --git a/src/Jackett/Indexers/MoreThanTV.cs b/src/Jackett/Indexers/MoreThanTV.cs index fc8ec80ba..0e2ac4ee4 100644 --- a/src/Jackett/Indexers/MoreThanTV.cs +++ b/src/Jackett/Indexers/MoreThanTV.cs @@ -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, diff --git a/src/Jackett/Indexers/MyAnonamouse.cs b/src/Jackett/Indexers/MyAnonamouse.cs index 234329fe0..9f022f479 100644 --- a/src/Jackett/Indexers/MyAnonamouse.cs +++ b/src/Jackett/Indexers/MyAnonamouse.cs @@ -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, diff --git a/src/Jackett/Indexers/NCore.cs b/src/Jackett/Indexers/NCore.cs index 9015b8c7e..3353cc731 100644 --- a/src/Jackett/Indexers/NCore.cs +++ b/src/Jackett/Indexers/NCore.cs @@ -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, diff --git a/src/Jackett/Indexers/NewRealWorld.cs b/src/Jackett/Indexers/NewRealWorld.cs index 6ee9411af..58a016eaf 100644 --- a/src/Jackett/Indexers/NewRealWorld.cs +++ b/src/Jackett/Indexers/NewRealWorld.cs @@ -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, diff --git a/src/Jackett/Indexers/Norbits.cs b/src/Jackett/Indexers/Norbits.cs index 67094c8b6..69517bd99 100644 --- a/src/Jackett/Indexers/Norbits.cs +++ b/src/Jackett/Indexers/Norbits.cs @@ -22,7 +22,7 @@ namespace Jackett.Indexers /// s /// Provider for Norbits Private Tracker /// - 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."); } } diff --git a/src/Jackett/Indexers/PassThePopcorn.cs b/src/Jackett/Indexers/PassThePopcorn.cs index 0ec27b150..4b7567927 100644 --- a/src/Jackett/Indexers/PassThePopcorn.cs +++ b/src/Jackett/Indexers/PassThePopcorn.cs @@ -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, diff --git a/src/Jackett/Indexers/PiXELHD.cs b/src/Jackett/Indexers/PiXELHD.cs index 199c3e57e..df72e7458 100644 --- a/src/Jackett/Indexers/PiXELHD.cs +++ b/src/Jackett/Indexers/PiXELHD.cs @@ -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, diff --git a/src/Jackett/Indexers/PirateTheNet.cs b/src/Jackett/Indexers/PirateTheNet.cs index 41188b18f..5237d040a 100644 --- a/src/Jackett/Indexers/PirateTheNet.cs +++ b/src/Jackett/Indexers/PirateTheNet.cs @@ -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, diff --git a/src/Jackett/Indexers/Pretome.cs b/src/Jackett/Indexers/Pretome.cs index 5a7a662bb..031a2ecd9 100644 --- a/src/Jackett/Indexers/Pretome.cs +++ b/src/Jackett/Indexers/Pretome.cs @@ -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()) diff --git a/src/Jackett/Indexers/PrivateHD.cs b/src/Jackett/Indexers/PrivateHD.cs index 89d182b85..f9e2b3e0b 100644 --- a/src/Jackett/Indexers/PrivateHD.cs +++ b/src/Jackett/Indexers/PrivateHD.cs @@ -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 diff --git a/src/Jackett/Indexers/Psytorrents.cs b/src/Jackett/Indexers/Psytorrents.cs index 8adafdf75..34e8a21fd 100644 --- a/src/Jackett/Indexers/Psytorrents.cs +++ b/src/Jackett/Indexers/Psytorrents.cs @@ -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 diff --git a/src/Jackett/Indexers/Rarbg.cs b/src/Jackett/Indexers/Rarbg.cs index 454b177ad..84d7c22d4 100644 --- a/src/Jackett/Indexers/Rarbg.cs +++ b/src/Jackett/Indexers/Rarbg.cs @@ -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, diff --git a/src/Jackett/Indexers/Redacted.cs b/src/Jackett/Indexers/Redacted.cs index 810dbebc0..046f82d08 100644 --- a/src/Jackett/Indexers/Redacted.cs +++ b/src/Jackett/Indexers/Redacted.cs @@ -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 diff --git a/src/Jackett/Indexers/RevolutionTT.cs b/src/Jackett/Indexers/RevolutionTT.cs index 88984998e..18de3a60e 100644 --- a/src/Jackett/Indexers/RevolutionTT.cs +++ b/src/Jackett/Indexers/RevolutionTT.cs @@ -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, diff --git a/src/Jackett/Indexers/SceneAccess.cs b/src/Jackett/Indexers/SceneAccess.cs index 3200b4e40..6ba2d2cfa 100644 --- a/src/Jackett/Indexers/SceneAccess.cs +++ b/src/Jackett/Indexers/SceneAccess.cs @@ -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, diff --git a/src/Jackett/Indexers/SceneFZ.cs b/src/Jackett/Indexers/SceneFZ.cs index c89bfd29d..7d0c86b19 100644 --- a/src/Jackett/Indexers/SceneFZ.cs +++ b/src/Jackett/Indexers/SceneFZ.cs @@ -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, diff --git a/src/Jackett/Indexers/SceneTime.cs b/src/Jackett/Indexers/SceneTime.cs index d2a6741d3..f1584e369 100644 --- a/src/Jackett/Indexers/SceneTime.cs +++ b/src/Jackett/Indexers/SceneTime.cs @@ -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, diff --git a/src/Jackett/Indexers/Shazbat.cs b/src/Jackett/Indexers/Shazbat.cs index b34b3c904..eb73efeee 100644 --- a/src/Jackett/Indexers/Shazbat.cs +++ b/src/Jackett/Indexers/Shazbat.cs @@ -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, diff --git a/src/Jackett/Indexers/ShowRSS.cs b/src/Jackett/Indexers/ShowRSS.cs index 50ce49b8d..72928bc09 100644 --- a/src/Jackett/Indexers/ShowRSS.cs +++ b/src/Jackett/Indexers/ShowRSS.cs @@ -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, diff --git a/src/Jackett/Indexers/SpeedCD.cs b/src/Jackett/Indexers/SpeedCD.cs index ce329699e..ed69bddb2 100644 --- a/src/Jackett/Indexers/SpeedCD.cs +++ b/src/Jackett/Indexers/SpeedCD.cs @@ -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, diff --git a/src/Jackett/Indexers/Superbits.cs b/src/Jackett/Indexers/Superbits.cs index 3e58dc297..72a4a6b51 100644 --- a/src/Jackett/Indexers/Superbits.cs +++ b/src/Jackett/Indexers/Superbits.cs @@ -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, diff --git a/src/Jackett/Indexers/T411.cs b/src/Jackett/Indexers/T411.cs index dc9460b6e..e46c240b1 100644 --- a/src/Jackett/Indexers/T411.cs +++ b/src/Jackett/Indexers/T411.cs @@ -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> _mediaCategoryMapping = new Dictionary>(); - 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, diff --git a/src/Jackett/Indexers/TVChaosUK.cs b/src/Jackett/Indexers/TVChaosUK.cs index 471b0bb45..aeddaaf97 100644 --- a/src/Jackett/Indexers/TVChaosUK.cs +++ b/src/Jackett/Indexers/TVChaosUK.cs @@ -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, diff --git a/src/Jackett/Indexers/TVVault.cs b/src/Jackett/Indexers/TVVault.cs index 5b175526d..74c730c7a 100644 --- a/src/Jackett/Indexers/TVVault.cs +++ b/src/Jackett/Indexers/TVVault.cs @@ -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, diff --git a/src/Jackett/Indexers/TehConnection.cs b/src/Jackett/Indexers/TehConnection.cs index 8e60be218..f6505eb2f 100644 --- a/src/Jackett/Indexers/TehConnection.cs +++ b/src/Jackett/Indexers/TehConnection.cs @@ -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, diff --git a/src/Jackett/Indexers/TorrentBytes.cs b/src/Jackett/Indexers/TorrentBytes.cs index e7209d794..9495eee6a 100644 --- a/src/Jackett/Indexers/TorrentBytes.cs +++ b/src/Jackett/Indexers/TorrentBytes.cs @@ -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, diff --git a/src/Jackett/Indexers/TorrentDay.cs b/src/Jackett/Indexers/TorrentDay.cs index 5bd19410d..e819aeee8 100644 --- a/src/Jackett/Indexers/TorrentDay.cs +++ b/src/Jackett/Indexers/TorrentDay.cs @@ -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, diff --git a/src/Jackett/Indexers/TorrentHeaven.cs b/src/Jackett/Indexers/TorrentHeaven.cs index 9fbbe940d..2362adee8 100644 --- a/src/Jackett/Indexers/TorrentHeaven.cs +++ b/src/Jackett/Indexers/TorrentHeaven.cs @@ -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 ApplyConfiguration(JToken configJson) { LoadValuesFromJson(configJson); - + var pairs = new Dictionary { { "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(); - + 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(); diff --git a/src/Jackett/Indexers/TorrentLeech.cs b/src/Jackett/Indexers/TorrentLeech.cs index 4cacd5814..db2341114 100644 --- a/src/Jackett/Indexers/TorrentLeech.cs +++ b/src/Jackett/Indexers/TorrentLeech.cs @@ -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, diff --git a/src/Jackett/Indexers/TorrentNetwork.cs b/src/Jackett/Indexers/TorrentNetwork.cs index c3fcc8e58..36717e927 100644 --- a/src/Jackett/Indexers/TorrentNetwork.cs +++ b/src/Jackett/Indexers/TorrentNetwork.cs @@ -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, diff --git a/src/Jackett/Indexers/TorrentSyndikat.cs b/src/Jackett/Indexers/TorrentSyndikat.cs index fb829b9e5..902542255 100644 --- a/src/Jackett/Indexers/TorrentSyndikat.cs +++ b/src/Jackett/Indexers/TorrentSyndikat.cs @@ -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, diff --git a/src/Jackett/Indexers/Torrentech.cs b/src/Jackett/Indexers/Torrentech.cs index 720c334d4..ce9210a32 100644 --- a/src/Jackett/Indexers/Torrentech.cs +++ b/src/Jackett/Indexers/Torrentech.cs @@ -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, diff --git a/src/Jackett/Indexers/TransmitheNet.cs b/src/Jackett/Indexers/TransmitheNet.cs index 86dfa3b5e..fa25954d9 100644 --- a/src/Jackett/Indexers/TransmitheNet.cs +++ b/src/Jackett/Indexers/TransmitheNet.cs @@ -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, diff --git a/src/Jackett/Indexers/Trezzor.cs b/src/Jackett/Indexers/Trezzor.cs index d1f9b29ca..b555a7aca 100644 --- a/src/Jackett/Indexers/Trezzor.cs +++ b/src/Jackett/Indexers/Trezzor.cs @@ -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, diff --git a/src/Jackett/Indexers/WiHD.cs b/src/Jackett/Indexers/WiHD.cs index 0fe78fba4..7b8051da9 100644 --- a/src/Jackett/Indexers/WiHD.cs +++ b/src/Jackett/Indexers/WiHD.cs @@ -21,7 +21,7 @@ namespace Jackett.Indexers /// /// Provider for WiHD Private French Tracker /// - 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 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); } diff --git a/src/Jackett/Indexers/XSpeeds.cs b/src/Jackett/Indexers/XSpeeds.cs index 050675ac7..4a074d6a6 100644 --- a/src/Jackett/Indexers/XSpeeds.cs +++ b/src/Jackett/Indexers/XSpeeds.cs @@ -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, diff --git a/src/Jackett/Indexers/Xthor.cs b/src/Jackett/Indexers/Xthor.cs index c1dcbac0a..2163425b0 100644 --- a/src/Jackett/Indexers/Xthor.cs +++ b/src/Jackett/Indexers/Xthor.cs @@ -20,7 +20,7 @@ namespace Jackett.Indexers /// /// Provider for Xthor Private French Tracker /// - 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 EmulatedBrowserHeaders { get; } = new Dictionary(); 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 /// /// Our params in Json /// Configuration state - #pragma warning disable 1998 +#pragma warning disable 1998 public override async Task 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); diff --git a/src/Jackett/Indexers/cgpeers.cs b/src/Jackett/Indexers/cgpeers.cs index b8ca01dd4..42817c466 100644 --- a/src/Jackett/Indexers/cgpeers.cs +++ b/src/Jackett/Indexers/cgpeers.cs @@ -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 diff --git a/src/Jackett/Indexers/myAmity.cs b/src/Jackett/Indexers/myAmity.cs index ad895be60..dd4bb4356 100644 --- a/src/Jackett/Indexers/myAmity.cs +++ b/src/Jackett/Indexers/myAmity.cs @@ -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, diff --git a/src/Jackett/Indexers/notwhatcd.cs b/src/Jackett/Indexers/notwhatcd.cs index ecfeac0d6..e2fca0f1f 100644 --- a/src/Jackett/Indexers/notwhatcd.cs +++ b/src/Jackett/Indexers/notwhatcd.cs @@ -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 diff --git a/src/Jackett/Indexers/rutracker.cs b/src/Jackett/Indexers/rutracker.cs index 89ab74148..7990086b1 100644 --- a/src/Jackett/Indexers/rutracker.cs +++ b/src/Jackett/Indexers/rutracker.cs @@ -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, diff --git a/src/Jackett/Indexers/x264.cs b/src/Jackett/Indexers/x264.cs index 359c37c24..8c8003755 100644 --- a/src/Jackett/Indexers/x264.cs +++ b/src/Jackett/Indexers/x264.cs @@ -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, diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj index 123acfacc..2cf721c26 100644 --- a/src/Jackett/Jackett.csproj +++ b/src/Jackett/Jackett.csproj @@ -377,6 +377,8 @@ + + @@ -573,8 +575,10 @@ - - + + + + diff --git a/src/Jackett/Models/IndexerDefinition.cs b/src/Jackett/Models/IndexerDefinition.cs new file mode 100644 index 000000000..449942b8f --- /dev/null +++ b/src/Jackett/Models/IndexerDefinition.cs @@ -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>, IDictionary + { + public selectorBlock this[string key] + { + get + { + throw new NotImplementedException(); + } + + set + { + base.Add(new KeyValuePair(key, value)); + } + } + + public ICollection Keys + { + get + { + throw new NotImplementedException(); + } + } + + public ICollection Values + { + get + { + throw new NotImplementedException(); + } + } + + public void Add(string key, selectorBlock value) + { + base.Add(new KeyValuePair(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 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 Links { get; set; } + public List 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 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 Categories { get; set; } + public List Categorymappings { get; set; } + public Dictionary> 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 Cookies { get; set; } + public string Method { get; set; } + public string Form { get; set; } + public bool Selectors { get; set; } = false; + public Dictionary Inputs { get; set; } + public Dictionary Selectorinputs { get; set; } + public Dictionary Getselectorinputs { get; set; } + public List 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 Filters { get; set; } + public Dictionary 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 Paths { get; set; } + public Dictionary> Headers { get; set; } + public List Keywordsfilters { get; set; } + public Dictionary Inputs { get; set; } + public List 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 Categories { get; set; } + public bool Inheritinputs { get; set; } = true; + } + + public class requestBlock + { + public string Path { get; set; } + public string Method { get; set; } + public Dictionary Inputs { get; set; } + } + + public class downloadBlock + { + public string Selector { get; set; } + public string Method { get; set; } + public requestBlock Before { get; set; } + } +} diff --git a/src/Jackett/Services/IndexerConfigurationService.cs b/src/Jackett/Services/IndexerConfigurationService.cs new file mode 100644 index 000000000..52735b435 --- /dev/null +++ b/src/Jackett/Services/IndexerConfigurationService.cs @@ -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("cookies"); + // configData.IncludeRaw.Value = jsonConfig.Value("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(); + } +} diff --git a/src/Jackett/Services/IndexerManagerService.cs b/src/Jackett/Services/IndexerManagerService.cs index fddee4e3b..6304e9ab0 100644 --- a/src/Jackett/Services/IndexerManagerService.cs +++ b/src/Jackett/Services/IndexerManagerService.cs @@ -9,9 +9,10 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; using System.Threading.Tasks; using Jackett.Indexers.Meta; +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; namespace Jackett.Services { @@ -20,8 +21,9 @@ namespace Jackett.Services Task TestIndexer(string name); void DeleteIndexer(string name); IIndexer GetIndexer(string name); + IWebIndexer GetWebIndexer(string name); IEnumerable GetAllIndexers(); - void SaveConfig(IIndexer indexer, JToken obj); + void InitIndexers(); void InitCardigannIndexers(string path); void InitAggregateIndexer(); @@ -30,16 +32,14 @@ namespace Jackett.Services public class IndexerManagerService : IIndexerManagerService { - private static readonly object configWriteLock = new object(); - private IContainer container; - private IConfigurationService configService; private Logger logger; private Dictionary indexers = new Dictionary(); private ICacheService cacheService; + private IIndexerConfigurationService configService; private AggregateIndexer aggregateIndexer; - public IndexerManagerService(IContainer c, IConfigurationService config, Logger l, ICacheService cache) + public IndexerManagerService(IContainer c, IIndexerConfigurationService config, Logger l, ICacheService cache) { container = c; configService = config; @@ -47,44 +47,6 @@ namespace Jackett.Services cacheService = cache; } - protected void LoadIndexerConfig(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 InitIndexers() { logger.Info("Using HTTP Client: " + container.Resolve().GetType().Name); @@ -92,7 +54,7 @@ namespace Jackett.Services foreach (var idx in container.Resolve>().Where(p => p.ID != "cardigannindexer" && p.ID != "aggregateindexer").OrderBy(_ => _.DisplayName)) { indexers.Add(idx.ID, idx); - LoadIndexerConfig(idx); + configService.Load(idx); } } @@ -111,7 +73,13 @@ namespace Jackett.Services { logger.Info("Loading Cardigann definition " + file.FullName); string DefinitionString = File.ReadAllText(file.FullName); - CardigannIndexer idx = new CardigannIndexer(this, container.Resolve(), logger, container.Resolve(), DefinitionString); + var deserializer = new DeserializerBuilder() + .WithNamingConvention(new CamelCaseNamingConvention()) + .IgnoreUnmatchedProperties() + .Build(); + var definition = deserializer.Deserialize(DefinitionString); + + CardigannIndexer idx = new CardigannIndexer(configService, container.Resolve(), logger, container.Resolve(), definition); if (indexers.ContainsKey(idx.ID)) { logger.Debug(string.Format("Ignoring definition ID={0}, file={1}: Indexer already exists", idx.ID, file.FullName)); @@ -119,13 +87,13 @@ namespace Jackett.Services else { indexers.Add(idx.ID, idx); - LoadIndexerConfig(idx); + configService.Load(idx); } } } catch (Exception ex) { - logger.Error(ex, "Error while loading Cardigann definitions: "+ ex.Message); + logger.Error(ex, "Error while loading Cardigann definitions: " + ex.Message); } } @@ -147,9 +115,8 @@ namespace Jackett.Services } logger.Info("Adding aggregate indexer"); - AggregateIndexer aggregateIndexer = new AggregateIndexer(fallbackStrategyProvider, resultFilterProvider, this, container.Resolve(), logger, container.Resolve()); - this.aggregateIndexer = aggregateIndexer; - UpdateAggregateIndexer(); + aggregateIndexer = new AggregateIndexer(fallbackStrategyProvider, resultFilterProvider, configService, container.Resolve(), logger, container.Resolve()); + aggregateIndexer.Indexers = indexers.Values; } public IIndexer GetIndexer(string name) @@ -169,6 +136,15 @@ namespace Jackett.Services } } + public IWebIndexer GetWebIndexer(string name) + { + if (indexers.ContainsKey(name)) + return indexers[name] as IWebIndexer; + + logger.Error("Request for unknown indexer: " + name); + throw new Exception("Unknown indexer: " + name); + } + public IEnumerable GetAllIndexers() { return indexers.Values; @@ -180,7 +156,6 @@ namespace Jackett.Services var browseQuery = new TorznabQuery(); browseQuery.IsTest = true; var results = await indexer.ResultsForQuery(browseQuery); - results = indexer.CleanLinks(results); logger.Info(string.Format("Found {0} releases from {1}", results.Count(), indexer.DisplayName)); if (results.Count() == 0) throw new Exception("Found no results while trying to browse this tracker"); @@ -190,84 +165,8 @@ namespace Jackett.Services public void DeleteIndexer(string name) { var indexer = GetIndexer(name); - var configPath = GetIndexerConfigFilePath(indexer); - File.Delete(configPath); - if (indexer.GetType() == typeof(CardigannIndexer)) - { - indexers[name] = new CardigannIndexer(this, container.Resolve(), logger, container.Resolve(), ((CardigannIndexer)indexer).DefinitionString); - } - else - { - indexers[name] = container.ResolveNamed(indexer.ID); - } - UpdateAggregateIndexer(); - } - - private string GetIndexerConfigFilePath(IIndexer indexer) - { - return Path.Combine(configService.GetIndexerConfigDir(), indexer.ID + ".json"); - } - - public void SaveConfig(IIndexer indexer, JToken obj) - { - UpdateAggregateIndexer(); - 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())); - } - } + configService.Delete(indexer); + indexer.Unconfigure(); } public void SortIndexers() @@ -279,10 +178,5 @@ namespace Jackett.Services newIndexers.Add(indexer.Key, indexer.Value); indexers = newIndexers; } - - private void UpdateAggregateIndexer() - { - aggregateIndexer.Indexers = indexers.Where(p => p.Value.IsConfigured).Select(p => p.Value); - } } } diff --git a/src/Jackett/Services/ServerService.cs b/src/Jackett/Services/ServerService.cs index 4e507f534..034db7f82 100644 --- a/src/Jackett/Services/ServerService.cs +++ b/src/Jackett/Services/ServerService.cs @@ -87,7 +87,7 @@ namespace Jackett.Services { if (link == null || (link.IsAbsoluteUri && link.Scheme == "magnet")) return link; - + var encodedLink = HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(link.ToString())); string urlEncodedFile = WebUtility.UrlEncode(file); var proxyLink = string.Format("{0}{1}/{2}/{3}?path={4}&file={5}", serverUrl, action, indexerId, config.APIKey, encodedLink, urlEncodedFile); @@ -96,7 +96,8 @@ namespace Jackett.Services public string BasePath() { - if (config.BasePathOverride == null || config.BasePathOverride == "") { + if (config.BasePathOverride == null || config.BasePathOverride == "") + { return "/"; } var path = config.BasePathOverride; @@ -226,7 +227,7 @@ namespace Jackett.Services { // Check for mono-devel // Is there any better way which doesn't involve a hard cashes? - var mono_devel_file = Path.Combine(runtimedir, "mono-api-info.exe"); + var mono_devel_file = Path.Combine(runtimedir, "mono-api-info.exe"); if (!File.Exists(mono_devel_file)) { var notice = "It looks like the mono-devel package is not installed, please make sure it's installed to avoid crashes."; @@ -250,12 +251,12 @@ namespace Jackett.Services var notice = "The ca-certificates-mono package is not installed, HTTPS trackers won't work. Please install it."; _notices.Add(notice); logger.Error(notice); - } + } else { logger.Info("The ca-certificates-mono package is not installed, it will become mandatory once mono >= 4.8 is used."); } - + } } catch (Exception e) @@ -283,7 +284,7 @@ namespace Jackett.Services CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); // Load indexers indexerService.InitIndexers(); - foreach(string dir in configService.GetCardigannDefinitionsFolders()) + foreach (string dir in configService.GetCardigannDefinitionsFolders()) { indexerService.InitCardigannIndexers(dir); } diff --git a/src/Jackett/Utils/Extensions.cs b/src/Jackett/Utils/Extensions.cs index 38bf6af37..3c5e68bfd 100644 --- a/src/Jackett/Utils/Extensions.cs +++ b/src/Jackett/Utils/Extensions.cs @@ -51,4 +51,17 @@ namespace Jackett.Utils return string.IsNullOrEmpty(str) || string.IsNullOrWhiteSpace(str); } } + + public static class CollectionExtension + { + public static bool IsEmpty(this ICollection obj) + { + return obj.Count == 0; + } + + public static bool IsEmptyOrNull(this ICollection obj) + { + return obj == null || obj.IsEmpty(); + } + } } diff --git a/src/Jackett/Utils/StringUtil.cs b/src/Jackett/Utils/StringUtil.cs index 0c91ffc55..5d96fa6e4 100644 --- a/src/Jackett/Utils/StringUtil.cs +++ b/src/Jackett/Utils/StringUtil.cs @@ -17,7 +17,7 @@ namespace Jackett.Utils { public static class StringUtil { - public static string StripNonAlphaNumeric(string str, string replacement = "") + public static string StripNonAlphaNumeric(this string str, string replacement = "") { return StripRegex(str, "[^a-zA-Z0-9 -]", replacement); } @@ -157,7 +157,7 @@ namespace Jackett.Utils return sb.ToString(); } - + public static string GenerateRandom(int length) {