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) {