2020-02-09 02:35:16 +00:00
using System ;
2017-04-15 08:45:10 +00:00
using System.Collections.Generic ;
using System.Collections.Specialized ;
2020-05-03 23:35:52 +00:00
using System.Diagnostics.CodeAnalysis ;
2018-03-01 11:38:27 +00:00
using System.Globalization ;
2017-04-15 08:45:10 +00:00
using System.Linq ;
2017-11-05 09:42:03 +00:00
using System.Net ;
2017-04-15 08:45:10 +00:00
using System.Text ;
using System.Text.RegularExpressions ;
using System.Threading.Tasks ;
2020-03-01 01:46:34 +00:00
using AngleSharp.Dom ;
using AngleSharp.Html.Dom ;
using AngleSharp.Html.Parser ;
2018-03-10 08:05:56 +00:00
using Jackett.Common.Models ;
using Jackett.Common.Models.IndexerConfig.Bespoke ;
using Jackett.Common.Services.Interfaces ;
using Jackett.Common.Utils ;
2017-04-15 08:45:10 +00:00
using Newtonsoft.Json.Linq ;
using NLog ;
2020-10-19 20:50:19 +00:00
using WebClient = Jackett . Common . Utils . Clients . WebClient ;
2017-04-15 08:45:10 +00:00
2018-03-10 08:05:56 +00:00
namespace Jackett.Common.Indexers
2017-04-15 08:45:10 +00:00
{
/// <summary>
/// Provider for Abnormal Private French Tracker
2018-03-01 11:38:27 +00:00
/// gazelle based but the ajax.php API seems to be broken (always returning failure)
2017-04-15 08:45:10 +00:00
/// </summary>
2020-05-03 23:35:52 +00:00
[ExcludeFromCodeCoverage]
2017-07-10 20:58:44 +00:00
public class Abnormal : BaseCachingWebIndexer
2017-04-15 08:45:10 +00:00
{
2020-02-25 16:08:03 +00:00
private string LoginUrl = > SiteLink + "login.php" ;
private string SearchUrl = > SiteLink + "torrents.php" ;
2020-11-08 02:11:27 +00:00
private string DetailsUrl = > SiteLink + "torrents.php?id=" ;
2020-02-25 16:08:03 +00:00
private string ReplaceMulti = > ConfigData . ReplaceMulti . Value ;
2017-04-15 08:45:10 +00:00
private ConfigurationDataAbnormal ConfigData
{
2020-02-25 16:08:03 +00:00
get = > ( ConfigurationDataAbnormal ) configData ;
2020-10-19 20:50:19 +00:00
set = > configData = value ;
2017-04-15 08:45:10 +00:00
}
2020-12-11 22:14:21 +00:00
public Abnormal ( IIndexerConfigurationService configService , WebClient w , Logger l , IProtectionService ps ,
ICacheService cs )
2020-05-11 19:59:28 +00:00
: base ( id : "abnormal" ,
name : "Abnormal" ,
description : "General French Private Tracker" ,
link : "https://abnormal.ws/" ,
2021-05-16 18:13:54 +00:00
caps : new TorznabCapabilities
{
2020-10-18 20:47:36 +00:00
TvSearchParams = new List < TvSearchParam >
{
TvSearchParam . Q , TvSearchParam . Season , TvSearchParam . Ep
} ,
MovieSearchParams = new List < MovieSearchParam >
{
MovieSearchParam . Q
}
2020-10-18 17:26:22 +00:00
} ,
2020-05-11 19:59:28 +00:00
configService : configService ,
client : w ,
logger : l ,
p : ps ,
2020-12-11 22:14:21 +00:00
cacheService : cs ,
2020-05-11 19:59:28 +00:00
downloadBase : "https://abnormal.ws/torrents.php?action=download&id=" ,
configData : new ConfigurationDataAbnormal ( ) )
2017-04-15 08:45:10 +00:00
{
Language = "fr-fr" ;
Encoding = Encoding . UTF8 ;
Type = "private" ;
2020-11-06 03:09:57 +00:00
AddCategoryMapping ( "MOVIE|DVDR" , TorznabCatType . MoviesDVD , "DVDR" ) ;
AddCategoryMapping ( "MOVIE|DVDRIP" , TorznabCatType . MoviesSD , "DVDRIP" ) ;
AddCategoryMapping ( "MOVIE|BDRIP" , TorznabCatType . MoviesSD , "BDRIP" ) ;
AddCategoryMapping ( "MOVIE|VOSTFR" , TorznabCatType . MoviesOther , "VOSTFR" ) ;
AddCategoryMapping ( "MOVIE|HD|720p" , TorznabCatType . MoviesHD , "HD 720P" ) ;
AddCategoryMapping ( "MOVIE|HD|1080p" , TorznabCatType . MoviesHD , "HD 1080P" ) ;
AddCategoryMapping ( "MOVIE|REMUXBR" , TorznabCatType . MoviesBluRay , "REMUX BLURAY" ) ;
AddCategoryMapping ( "MOVIE|FULLBR" , TorznabCatType . MoviesBluRay , "FULL BLURAY" ) ;
AddCategoryMapping ( "TV|SD|VOSTFR" , TorznabCatType . TV , "TV SD VOSTFR" ) ;
AddCategoryMapping ( "TV|HD|VOSTFR" , TorznabCatType . TVHD , "TV HD VOSTFR" ) ;
AddCategoryMapping ( "TV|SD|VF" , TorznabCatType . TVSD , "TV SD VF" ) ;
AddCategoryMapping ( "TV|HD|VF" , TorznabCatType . TVHD , "TV HD VF" ) ;
AddCategoryMapping ( "TV|PACK|FR" , TorznabCatType . TVOther , "TV PACK FR" ) ;
AddCategoryMapping ( "TV|PACK|VOSTFR" , TorznabCatType . TVOther , "TV PACK VOSTFR" ) ;
AddCategoryMapping ( "TV|EMISSIONS" , TorznabCatType . TVOther , "TV EMISSIONS" ) ;
AddCategoryMapping ( "ANIME" , TorznabCatType . TVAnime , "ANIME" ) ;
AddCategoryMapping ( "DOCS" , TorznabCatType . TVDocumentary , "TV DOCS" ) ;
AddCategoryMapping ( "MUSIC|FLAC" , TorznabCatType . AudioLossless , "FLAC" ) ;
AddCategoryMapping ( "MUSIC|MP3" , TorznabCatType . AudioMP3 , "MP3" ) ;
AddCategoryMapping ( "MUSIC|CONCERT" , TorznabCatType . AudioVideo , "CONCERT" ) ;
AddCategoryMapping ( "PC|APP" , TorznabCatType . PC , "PC" ) ;
AddCategoryMapping ( "PC|GAMES" , TorznabCatType . PCGames , "GAMES" ) ;
AddCategoryMapping ( "EBOOKS" , TorznabCatType . BooksEBook , "EBOOKS" ) ;
2017-04-15 08:45:10 +00:00
}
/// <summary>
/// Configure our WiHD Provider
/// </summary>
/// <param name="configJson">Our params in Json</param>
/// <returns>Configuration state</returns>
2017-06-28 05:31:38 +00:00
public override async Task < IndexerConfigurationStatus > ApplyConfiguration ( JToken configJson )
2017-04-15 08:45:10 +00:00
{
// Retrieve config values set by Jackett's user
LoadValuesFromJson ( configJson ) ;
// Check & Validate Config
2021-05-05 14:52:20 +00:00
ValidateConfig ( ) ;
2017-04-15 08:45:10 +00:00
// Building login form data
var pairs = new Dictionary < string , string > {
{ "username" , ConfigData . Username . Value } ,
{ "password" , ConfigData . Password . Value } ,
{ "keeplogged" , "1" } ,
{ "login" , "Connexion" }
} ;
// Perform loggin
2021-05-05 14:52:20 +00:00
logger . Info ( "\nAbnormal - Perform loggin.. with " + LoginUrl ) ;
2021-05-05 19:05:31 +00:00
var response = await RequestLoginAndFollowRedirect ( LoginUrl , pairs , null , true , null , LoginUrl , true ) ;
2017-04-15 08:45:10 +00:00
// Test if we are logged in
await ConfigureIfOK ( response . Cookies , response . Cookies . Contains ( "session=" ) , ( ) = >
{
// Parse error page
2020-03-01 01:46:34 +00:00
var parser = new HtmlParser ( ) ;
2020-06-09 17:36:57 +00:00
var dom = parser . ParseDocument ( response . ContentString ) ;
2020-03-01 01:46:34 +00:00
var message = dom . QuerySelector ( ".warning" ) . TextContent . Split ( '.' ) . Reverse ( ) . Skip ( 1 ) . First ( ) ;
2017-04-15 08:45:10 +00:00
// Try left
2020-03-01 01:46:34 +00:00
var left = dom . QuerySelector ( ".info" ) . TextContent . Trim ( ) ;
2017-04-15 08:45:10 +00:00
// Oops, unable to login
2021-05-05 14:52:20 +00:00
logger . Info ( "Abnormal - Login failed: \"" + message + "\" and " + left + " tries left before being banned for 6 hours !" , "error" ) ;
2021-05-05 19:05:31 +00:00
throw new ExceptionWithConfigData ( "Abnormal - Login failed: " + message , configData ) ;
2017-04-15 08:45:10 +00:00
} ) ;
2021-05-05 14:52:20 +00:00
logger . Info ( "-> Login Success" ) ;
2017-04-15 08:45:10 +00:00
return IndexerConfigurationStatus . RequiresTesting ;
}
/// <summary>
/// Execute our search query
/// </summary>
/// <param name="query">Query</param>
/// <returns>Releases</returns>
2017-07-03 05:15:47 +00:00
protected override async Task < IEnumerable < ReleaseInfo > > PerformQuery ( TorznabQuery query )
2017-04-15 08:45:10 +00:00
{
2020-02-10 22:16:19 +00:00
var startTransition = TimeZoneInfo . TransitionTime . CreateFloatingDateRule ( new DateTime ( 1 , 1 , 1 , 3 , 0 , 0 ) , 3 , 5 , DayOfWeek . Sunday ) ;
var endTransition = TimeZoneInfo . TransitionTime . CreateFloatingDateRule ( new DateTime ( 1 , 1 , 1 , 4 , 0 , 0 ) , 10 , 5 , DayOfWeek . Sunday ) ;
var delta = new TimeSpan ( 1 , 0 , 0 ) ;
var adjustment = TimeZoneInfo . AdjustmentRule . CreateAdjustmentRule ( new DateTime ( 1999 , 10 , 1 ) , DateTime . MaxValue . Date , delta , startTransition , endTransition ) ;
2018-03-01 11:38:27 +00:00
TimeZoneInfo . AdjustmentRule [ ] adjustments = { adjustment } ;
2020-02-10 22:16:19 +00:00
var FranceTz = 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 ) ;
2018-03-01 11:38:27 +00:00
2017-04-15 08:45:10 +00:00
var releases = new List < ReleaseInfo > ( ) ;
2020-03-01 01:46:34 +00:00
var qRowList = new List < IElement > ( ) ;
2017-04-15 08:45:10 +00:00
var searchTerm = query . GetQueryString ( ) ;
var searchUrl = SearchUrl ;
// Build our query
2021-05-05 14:52:20 +00:00
var request = BuildQuery ( searchTerm , query , searchUrl ) ;
2017-04-15 08:45:10 +00:00
// Getting results & Store content
2020-03-01 01:46:34 +00:00
var parser = new HtmlParser ( ) ;
2021-05-05 14:52:20 +00:00
var dom = parser . ParseDocument ( await QueryExecAsync ( request ) ) ;
2017-04-15 08:45:10 +00:00
try
{
// Find torrent rows
2021-05-05 14:52:20 +00:00
var firstPageRows = FindTorrentRows ( dom ) ;
2017-04-15 08:45:10 +00:00
// Add them to torrents list
2020-03-01 01:46:34 +00:00
qRowList . AddRange ( firstPageRows ) ;
2017-04-15 08:45:10 +00:00
// Check if there are pagination links at bottom
2020-03-01 01:46:34 +00:00
var qPagination = dom . QuerySelectorAll ( ".linkbox > a" ) ;
2021-05-05 14:52:20 +00:00
int pageLinkCount ;
int nbResults ;
2020-03-01 01:46:34 +00:00
if ( qPagination . Length > 0 )
2017-07-10 20:58:44 +00:00
{
2017-04-15 08:45:10 +00:00
// Calculate numbers of pages available for this search query (Based on number results and number of torrents on first page)
2020-03-01 01:46:34 +00:00
pageLinkCount = ParseUtil . CoerceInt ( Regex . Match ( qPagination . Last ( ) . GetAttribute ( "href" ) . ToString ( ) , @"\d+" ) . Value ) ;
2017-04-15 08:45:10 +00:00
// Calculate average number of results (based on torrents rows lenght on first page)
2020-03-01 01:46:34 +00:00
nbResults = firstPageRows . Length * pageLinkCount ;
2017-04-15 08:45:10 +00:00
}
2017-07-10 20:58:44 +00:00
else
{
2017-04-15 08:45:10 +00:00
// Check if we have a minimum of one result
if ( firstPageRows . Length > = 1 )
{
// Retrieve total count on our alone page
2020-03-01 01:46:34 +00:00
nbResults = firstPageRows . Length ;
2017-04-15 08:45:10 +00:00
pageLinkCount = 1 ;
}
else
{
2021-05-05 14:52:20 +00:00
logger . Info ( "\nAbnormal - No result found for your query, please try another search term ...\n" , "info" ) ;
2017-04-15 08:45:10 +00:00
// No result found for this query
return releases ;
}
}
2021-05-05 14:52:20 +00:00
logger . Info ( "\nAbnormal - Found " + nbResults + " result(s) (+/- " + firstPageRows . Length + ") in " + pageLinkCount + " page(s) for this query !" ) ;
logger . Info ( "\nAbnormal - There are " + firstPageRows . Length + " results on the first page !" ) ;
2017-04-15 08:45:10 +00:00
// If we have a term used for search and pagination result superior to one
if ( ! string . IsNullOrWhiteSpace ( query . GetQueryString ( ) ) & & pageLinkCount > 1 )
{
// Starting with page #2
2020-02-10 22:16:19 +00:00
for ( var i = 2 ; i < = Math . Min ( int . Parse ( ConfigData . Pages . Value ) , pageLinkCount ) ; i + + )
2017-04-15 08:45:10 +00:00
{
2021-05-05 14:52:20 +00:00
logger . Info ( "\nAbnormal - Processing page #" + i ) ;
2017-04-15 08:45:10 +00:00
// Build our query
2021-05-05 14:52:20 +00:00
var pageRequest = BuildQuery ( searchTerm , query , searchUrl , i ) ;
2017-04-15 08:45:10 +00:00
// Getting results & Store content
2020-03-01 01:46:34 +00:00
parser = new HtmlParser ( ) ;
2021-05-05 14:52:20 +00:00
dom = parser . ParseDocument ( await QueryExecAsync ( pageRequest ) ) ;
2017-04-15 08:45:10 +00:00
// Process page results
2021-05-05 14:52:20 +00:00
var additionalPageRows = FindTorrentRows ( dom ) ;
2017-04-15 08:45:10 +00:00
// Add them to torrents list
2020-03-01 01:46:34 +00:00
qRowList . AddRange ( additionalPageRows ) ;
2017-04-15 08:45:10 +00:00
}
}
// Loop on results
2020-03-01 01:46:34 +00:00
foreach ( var row in qRowList )
2017-04-15 08:45:10 +00:00
{
// ID
2020-03-01 01:46:34 +00:00
var id = ParseUtil . CoerceInt ( Regex . Match ( row . QuerySelector ( "td:nth-of-type(2) > a" ) . GetAttribute ( "href" ) , @"\d+" ) . Value ) ;
2017-04-15 08:45:10 +00:00
// Release Name
2020-03-01 01:46:34 +00:00
var name = row . QuerySelector ( "td:nth-of-type(2) > a" ) . TextContent ;
2019-05-05 21:13:10 +00:00
//issue #3847 replace multi keyword
2020-02-09 02:35:16 +00:00
if ( ! string . IsNullOrEmpty ( ReplaceMulti ) )
{
2020-02-10 22:16:19 +00:00
var regex = new Regex ( "(?i)([\\.\\- ])MULTI([\\.\\- ])" ) ;
2020-02-09 02:35:16 +00:00
name = regex . Replace ( name , "$1" + ReplaceMulti + "$2" ) ;
2019-05-05 21:13:10 +00:00
}
2017-04-15 08:45:10 +00:00
2021-05-05 14:52:20 +00:00
var categoryId = row . QuerySelector ( "td:nth-of-type(1) > a" ) . GetAttribute ( "href" ) . Replace ( "torrents.php?cat[]=" , string . Empty ) ; // Category
var newznab = MapTrackerCatToNewznab ( categoryId ) ; // Newznab Category
var seeders = ParseUtil . CoerceInt ( Regex . Match ( row . QuerySelector ( "td:nth-of-type(6)" ) . TextContent , @"\d+" ) . Value ) ; // Seeders
var leechers = ParseUtil . CoerceInt ( Regex . Match ( row . QuerySelector ( "td:nth-of-type(7)" ) . TextContent , @"\d+" ) . Value ) ; // Leechers
var completed = ParseUtil . CoerceInt ( Regex . Match ( row . QuerySelector ( "td:nth-of-type(6)" ) . TextContent , @"\d+" ) . Value ) ; // Completed
var sizeStr = row . QuerySelector ( "td:nth-of-type(5)" ) . TextContent . Replace ( "Go" , "gb" ) . Replace ( "Mo" , "mb" ) . Replace ( "Ko" , "kb" ) ; // Size
var size = ReleaseInfo . GetBytes ( sizeStr ) ; // Size in bytes
2017-04-15 08:45:10 +00:00
// Publish DateToString
2020-03-01 01:46:34 +00:00
var datestr = row . QuerySelector ( "span.time" ) . GetAttribute ( "title" ) ;
2018-03-01 11:38:27 +00:00
var dateLocal = DateTime . SpecifyKind ( DateTime . ParseExact ( datestr , "MMM dd yyyy, HH:mm" , CultureInfo . InvariantCulture ) , DateTimeKind . Unspecified ) ;
var date = TimeZoneInfo . ConvertTimeToUtc ( dateLocal , FranceTz ) ;
2017-04-15 08:45:10 +00:00
// Torrent Details URL
2020-11-08 02:11:27 +00:00
var details = new Uri ( DetailsUrl + id ) ;
2017-04-15 08:45:10 +00:00
// Torrent Download URL
2017-08-13 22:15:11 +00:00
Uri downloadLink = null ;
2020-03-01 01:46:34 +00:00
var link = row . QuerySelector ( "td:nth-of-type(4) > a" ) . GetAttribute ( "href" ) ;
2020-02-10 22:16:19 +00:00
if ( ! string . IsNullOrEmpty ( link ) )
2017-08-13 22:15:11 +00:00
{
// Download link available
downloadLink = new Uri ( SiteLink + link ) ;
}
else
{
// No download link available -- Must be on pending ( can't be downloaded now...)
2021-05-05 14:52:20 +00:00
logger . Info ( "Abnormal - Download Link: Not available, torrent pending ? Skipping ..." ) ;
2017-08-13 22:15:11 +00:00
continue ;
}
2017-04-15 08:45:10 +00:00
2017-08-13 22:15:11 +00:00
// Freeleech
2020-02-10 22:16:19 +00:00
var downloadVolumeFactor = 1 ;
2020-03-01 01:46:34 +00:00
if ( row . QuerySelector ( "img[alt=\"Freeleech\"]" ) ! = null )
2017-08-13 22:15:11 +00:00
{
downloadVolumeFactor = 0 ;
}
2017-04-15 08:45:10 +00:00
2017-08-13 22:15:11 +00:00
// Building release infos
2020-03-01 01:46:34 +00:00
var release = new ReleaseInfo
2017-08-13 22:15:11 +00:00
{
2020-03-01 01:46:34 +00:00
Category = MapTrackerCatToNewznab ( categoryId ) ,
2017-08-13 22:15:11 +00:00
Title = name ,
Seeders = seeders ,
Peers = seeders + leechers ,
PublishDate = date ,
Size = size ,
2020-11-08 02:11:27 +00:00
Guid = details ,
Details = details ,
2017-08-13 22:15:11 +00:00
Link = downloadLink ,
2020-01-11 18:07:19 +00:00
MinimumRatio = 1 ,
MinimumSeedTime = 172800 , // 48 hours
2017-08-13 22:15:11 +00:00
UploadVolumeFactor = 1 ,
DownloadVolumeFactor = downloadVolumeFactor
} ;
2017-04-15 08:45:10 +00:00
releases . Add ( release ) ;
2021-05-05 14:52:20 +00:00
logger . Info ( "Abnormal - Found Release: " + release . Title + "(" + id + ")" ) ;
2017-04-15 08:45:10 +00:00
}
}
catch ( Exception ex )
{
OnParseError ( "Error, unable to parse result \n" + ex . StackTrace , ex ) ;
}
// Return found releases
return releases ;
}
/// <summary>
/// Build query to process
/// </summary>
/// <param name="term">Term to search</param>
/// <param name="query">Torznab Query for categories mapping</param>
/// <param name="url">Search url for provider</param>
/// <param name="page">Page number to request</param>
/// <returns>URL to query for parsing and processing results</returns>
2021-05-05 14:52:20 +00:00
private string BuildQuery ( string term , TorznabQuery query , string url , int page = 0 )
2017-04-15 08:45:10 +00:00
{
var parameters = new NameValueCollection ( ) ;
2020-02-10 22:16:19 +00:00
var categoriesList = MapTorznabCapsToTrackers ( query ) ;
2017-04-15 08:45:10 +00:00
string categories = null ;
// Check if we are processing a new page
if ( page > 0 )
{
// Adding page number to query
parameters . Add ( "page" , page . ToString ( ) ) ;
}
// Loop on Categories needed
2020-02-10 22:16:19 +00:00
foreach ( var category in categoriesList )
2017-04-15 08:45:10 +00:00
{
// If last, build !
if ( categoriesList . Last ( ) = = category )
{
// Adding previous categories to URL with latest category
2017-11-05 09:42:03 +00:00
parameters . Add ( Uri . EscapeDataString ( "cat[]" ) , WebUtility . UrlEncode ( category ) + categories ) ;
2017-04-15 08:45:10 +00:00
}
else
{
// Build categories parameter
2017-11-05 09:42:03 +00:00
categories + = "&" + Uri . EscapeDataString ( "cat[]" ) + "=" + WebUtility . UrlEncode ( category ) ;
2017-04-15 08:45:10 +00:00
}
}
// If search term provided
if ( ! string . IsNullOrWhiteSpace ( term ) )
{
// Add search term
2017-11-05 09:42:03 +00:00
parameters . Add ( "search" , WebUtility . UrlEncode ( term ) ) ;
2017-04-15 08:45:10 +00:00
}
else
{
2017-11-05 09:42:03 +00:00
parameters . Add ( "search" , WebUtility . UrlEncode ( "%" ) ) ;
2017-04-15 08:45:10 +00:00
// Showing all torrents (just for output function)
term = "all" ;
}
// Building our query -- Cannot use GetQueryString due to UrlEncode (generating wrong cat[] param)
url + = "?" + string . Join ( "&" , parameters . AllKeys . Select ( a = > a + "=" + parameters [ a ] ) ) ;
2021-05-05 14:52:20 +00:00
logger . Info ( "\nAbnormal - Builded query for \"" + term + "\"... " + url ) ;
2017-04-15 08:45:10 +00:00
// Return our search url
return url ;
}
/// <summary>
/// Switch Method for Querying
/// </summary>
/// <param name="request">URL created by Query Builder</param>
/// <returns>Results from query</returns>
2021-05-05 14:52:20 +00:00
private async Task < string > QueryExecAsync ( string request )
2017-04-15 08:45:10 +00:00
{
2020-02-10 22:16:19 +00:00
string results = null ;
2017-04-15 08:45:10 +00:00
2021-05-05 14:52:20 +00:00
// Querying tracker directly
results = await QueryTrackerAsync ( request ) ;
2017-08-13 22:15:11 +00:00
2017-04-15 08:45:10 +00:00
return results ;
}
/// <summary>
/// Get Torrents Page from Tracker by Query Provided
/// </summary>
/// <param name="request">URL created by Query Builder</param>
/// <returns>Results from query</returns>
2021-05-05 14:52:20 +00:00
private async Task < string > QueryTrackerAsync ( string request )
2017-04-15 08:45:10 +00:00
{
// Cache mode not enabled or cached file didn't exist for our query
2021-05-05 14:52:20 +00:00
logger . Info ( "\nAbnormal - Querying tracker for results...." ) ;
2017-04-15 08:45:10 +00:00
// Request our first page
2021-05-05 14:52:20 +00:00
var results = await RequestWithCookiesAndRetryAsync ( request ) ;
2017-04-15 08:45:10 +00:00
// Return results from tracker
2020-06-09 17:36:57 +00:00
return results . ContentString ;
2017-04-15 08:45:10 +00:00
}
/// <summary>
/// Find torrent rows in search pages
/// </summary>
2020-03-01 01:46:34 +00:00
/// <returns>List of rows</returns>
2021-05-05 14:52:20 +00:00
private IHtmlCollection < IElement > FindTorrentRows ( IHtmlDocument dom ) = >
2020-03-01 01:46:34 +00:00
dom . QuerySelectorAll ( ".torrent_table > tbody > tr:not(.colhead)" ) ;
2017-04-15 08:45:10 +00:00
/// <summary>
/// Validate Config entered by user on Jackett
/// </summary>
2021-05-05 14:52:20 +00:00
private void ValidateConfig ( )
2017-04-15 08:45:10 +00:00
{
2021-05-05 14:52:20 +00:00
logger . Info ( "\nAbnormal - Validating Settings ... \n" ) ;
2017-04-15 08:45:10 +00:00
// Check Username Setting
if ( string . IsNullOrEmpty ( ConfigData . Username . Value ) )
{
throw new ExceptionWithConfigData ( "You must provide a username for this tracker to login !" , ConfigData ) ;
}
else
{
2021-05-05 14:52:20 +00:00
logger . Info ( "Abnormal - Validated Setting -- Username (auth) => " + ConfigData . Username . Value . ToString ( ) ) ;
2017-04-15 08:45:10 +00:00
}
// Check Password Setting
if ( string . IsNullOrEmpty ( ConfigData . Password . Value ) )
{
throw new ExceptionWithConfigData ( "You must provide a password with your username for this tracker to login !" , ConfigData ) ;
}
else
{
2021-05-05 14:52:20 +00:00
logger . Info ( "Abnormal - Validated Setting -- Password (auth) => " + ConfigData . Password . Value . ToString ( ) ) ;
2017-04-15 08:45:10 +00:00
}
// Check Max Page Setting
if ( ! string . IsNullOrEmpty ( ConfigData . Pages . Value ) )
{
try
{
2021-05-05 14:52:20 +00:00
logger . Info ( "Abnormal - Validated Setting -- Max Pages => " + Convert . ToInt32 ( ConfigData . Pages . Value ) ) ;
2017-04-15 08:45:10 +00:00
}
catch ( Exception )
{
throw new ExceptionWithConfigData ( "Please enter a numeric maximum number of pages to crawl !" , ConfigData ) ;
}
}
else
{
throw new ExceptionWithConfigData ( "Please enter a maximum number of pages to crawl !" , ConfigData ) ;
}
}
}
2020-02-09 02:35:16 +00:00
}