2020-02-09 02:35:16 +00:00
using System ;
2015-07-26 03:48:18 +00:00
using System.Collections.Generic ;
2017-10-29 06:21:18 +00:00
using System.Collections.Specialized ;
2020-05-03 23:35:52 +00:00
using System.Diagnostics.CodeAnalysis ;
2020-03-15 21:38:54 +00:00
using System.Linq ;
2015-07-26 03:48:18 +00:00
using System.Text ;
2017-10-29 06:21:18 +00:00
using System.Text.RegularExpressions ;
2015-07-26 03:48:18 +00:00
using System.Threading.Tasks ;
2020-02-28 22:32:02 +00:00
using AngleSharp.Html.Parser ;
2018-03-10 08:05:56 +00:00
using Jackett.Common.Models ;
using Jackett.Common.Models.IndexerConfig ;
using Jackett.Common.Services.Interfaces ;
using Jackett.Common.Utils ;
using Jackett.Common.Utils.Clients ;
2017-10-29 06:21:18 +00:00
using Newtonsoft.Json.Linq ;
using NLog ;
2021-02-04 08:50:28 +00:00
using static Jackett . Common . Models . IndexerConfig . ConfigurationData ;
2017-04-15 08:45:10 +00:00
2018-03-10 08:05:56 +00:00
namespace Jackett.Common.Indexers
2015-07-26 03:48:18 +00:00
{
2020-05-03 23:35:52 +00:00
[ExcludeFromCodeCoverage]
2017-07-10 20:58:44 +00:00
public class HDSpace : BaseWebIndexer
2015-07-26 03:48:18 +00:00
{
2020-02-25 16:08:03 +00:00
private string LoginUrl = > SiteLink + "index.php?page=login" ;
private string SearchUrl = > SiteLink + "index.php?page=torrents&" ;
2015-07-26 03:48:18 +00:00
2020-05-03 23:00:04 +00:00
private new ConfigurationDataBasicLogin configData = > ( ConfigurationDataBasicLogin ) base . configData ;
2015-08-03 21:38:45 +00:00
2020-12-11 22:14:21 +00:00
public HDSpace ( IIndexerConfigurationService configService , WebClient wc , Logger l , IProtectionService ps ,
ICacheService cs )
2020-05-11 19:59:28 +00:00
: base ( id : "hdspace" ,
name : "HD-Space" ,
2020-02-28 22:32:02 +00:00
description : "Sharing The Universe" ,
link : "https://hd-space.org/" ,
2020-10-13 20:17:26 +00:00
caps : new TorznabCapabilities
{
2020-10-18 20:47:36 +00:00
TvSearchParams = new List < TvSearchParam >
{
TvSearchParam . Q , TvSearchParam . Season , TvSearchParam . Ep , TvSearchParam . ImdbId
} ,
MovieSearchParams = new List < MovieSearchParam >
{
MovieSearchParam . Q , MovieSearchParam . ImdbId
2020-10-20 00:38:27 +00:00
} ,
MusicSearchParams = new List < MusicSearchParam >
{
MusicSearchParam . Q
2020-10-18 20:47:36 +00:00
}
2020-10-13 20:17:26 +00:00
} ,
2020-02-28 22:32:02 +00:00
configService : configService ,
client : wc ,
logger : l ,
p : ps ,
2020-12-11 22:14:21 +00:00
cacheService : cs ,
2020-05-03 23:00:04 +00:00
configData : new ConfigurationDataBasicLogin ( ) )
2015-07-26 03:48:18 +00:00
{
2017-11-05 09:42:03 +00:00
Encoding = Encoding . UTF8 ;
2021-09-08 01:14:00 +00:00
Language = "en-US" ;
2017-01-27 15:57:32 +00:00
Type = "private" ;
2016-12-06 13:56:47 +00:00
2022-04-17 06:20:52 +00:00
configData . AddDynamic ( "flaresolverr" , new DisplayInfoConfigurationItem ( "FlareSolverr" , "This site may use Cloudflare DDoS Protection, therefore Jackett requires <a href=\"https://github.com/Jackett/Jackett#configuring-flaresolverr\" target=\"_blank\">FlareSolverr</a> to access it." ) ) ;
2021-02-04 08:34:52 +00:00
2020-11-22 08:02:07 +00:00
AddCategoryMapping ( 15 , TorznabCatType . MoviesBluRay , "Movie / Blu-ray" ) ;
AddCategoryMapping ( 19 , TorznabCatType . MoviesHD , "Movie / 1080p" ) ;
AddCategoryMapping ( 18 , TorznabCatType . MoviesHD , "Movie / 720p" ) ;
AddCategoryMapping ( 40 , TorznabCatType . MoviesHD , "Movie / Remux" ) ;
AddCategoryMapping ( 16 , TorznabCatType . MoviesHD , "Movie / HD-DVD" ) ;
AddCategoryMapping ( 41 , TorznabCatType . MoviesUHD , "Movie / 4K UHD" ) ;
AddCategoryMapping ( 21 , TorznabCatType . TVHD , "TV Show / 720p HDTV" ) ;
AddCategoryMapping ( 22 , TorznabCatType . TVHD , "TV Show / 1080p HDTV" ) ;
AddCategoryMapping ( 24 , TorznabCatType . TVDocumentary , "Documentary / 720p" ) ;
AddCategoryMapping ( 25 , TorznabCatType . TVDocumentary , "Documentary / 1080p" ) ;
AddCategoryMapping ( 27 , TorznabCatType . TVAnime , "Animation / 720p" ) ;
AddCategoryMapping ( 28 , TorznabCatType . TVAnime , "Animation / 1080p" ) ;
AddCategoryMapping ( 30 , TorznabCatType . AudioLossless , "Music / HQ Audio" ) ;
AddCategoryMapping ( 31 , TorznabCatType . AudioVideo , "Music / Videos" ) ;
AddCategoryMapping ( 33 , TorznabCatType . XXX , "XXX / 720p" ) ;
AddCategoryMapping ( 34 , TorznabCatType . XXX , "XXX / 1080p" ) ;
AddCategoryMapping ( 36 , TorznabCatType . MoviesOther , "Trailers" ) ;
AddCategoryMapping ( 37 , TorznabCatType . PC , "Software" ) ;
AddCategoryMapping ( 38 , TorznabCatType . Other , "Others" ) ;
2017-10-29 06:21:18 +00:00
}
2015-07-26 03:48:18 +00:00
2017-06-28 05:31:38 +00:00
public override async Task < IndexerConfigurationStatus > ApplyConfiguration ( JToken configJson )
2015-07-26 03:48:18 +00:00
{
2017-01-02 20:39:28 +00:00
LoadValuesFromJson ( configJson ) ;
2020-09-21 16:39:47 +00:00
var loginPage = await RequestWithCookiesAsync ( LoginUrl , string . Empty ) ;
2020-02-28 22:32:02 +00:00
var pairs = new Dictionary < string , string >
{
{ "uid" , configData . Username . Value } ,
{ "pwd" , configData . Password . Value }
2015-07-26 03:48:18 +00:00
} ;
// Send Post
2020-03-15 21:38:54 +00:00
var response = await RequestLoginAndFollowRedirect ( LoginUrl , pairs , loginPage . Cookies , true , referer : LoginUrl ) ;
2015-07-26 03:48:18 +00:00
2020-06-09 17:36:57 +00:00
await ConfigureIfOK ( response . Cookies , response . ContentString ? . Contains ( "logout.php" ) = = true , ( ) = >
2015-07-26 03:48:18 +00:00
{
var errorStr = "You have {0} remaining login attempts" ;
2020-02-28 22:32:02 +00:00
var remainingAttemptSpan = new Regex ( string . Format ( errorStr , "(.*?)" ) )
2020-06-09 17:36:57 +00:00
. Match ( loginPage . ContentString ) . Groups [ 1 ] . ToString ( ) ;
2020-02-10 22:16:19 +00:00
var attempts = Regex . Replace ( remainingAttemptSpan , "<.*?>" , string . Empty ) ;
2015-07-26 03:48:18 +00:00
var errorMessage = string . Format ( errorStr , attempts ) ;
2015-08-03 21:38:45 +00:00
throw new ExceptionWithConfigData ( errorMessage , configData ) ;
2015-07-26 03:48:18 +00:00
} ) ;
2015-08-22 20:57:13 +00:00
return IndexerConfigurationStatus . RequiresTesting ;
2015-07-26 03:48:18 +00:00
}
2017-07-03 05:15:47 +00:00
protected override async Task < IEnumerable < ReleaseInfo > > PerformQuery ( TorznabQuery query )
2015-07-26 03:48:18 +00:00
{
2015-07-28 23:10:04 +00:00
var releases = new List < ReleaseInfo > ( ) ;
2020-02-28 22:32:02 +00:00
var queryCollection = new NameValueCollection
{
{ "active" , "0" } ,
{ "category" , string . Join ( ";" , MapTorznabCapsToTrackers ( query ) ) }
} ;
2016-10-27 16:50:58 +00:00
2020-03-15 21:38:54 +00:00
if ( query . IsImdbQuery )
{
queryCollection . Add ( "options" , "2" ) ;
queryCollection . Add ( "search" , query . ImdbIDShort ) ;
}
else
{
queryCollection . Add ( "options" , "0" ) ;
queryCollection . Add ( "search" , query . GetQueryString ( ) ) ;
}
2017-04-15 08:45:10 +00:00
2022-02-18 19:44:58 +00:00
// remove . as not used in titles
var response = await RequestWithCookiesAndRetryAsync ( SearchUrl + queryCollection . GetQueryString ( ) . Replace ( "." , " " ) ) ;
2015-07-26 03:48:18 +00:00
try
{
2020-02-28 22:32:02 +00:00
var resultParser = new HtmlParser ( ) ;
2020-06-09 17:36:57 +00:00
var searchResultDocument = resultParser . ParseDocument ( response . ContentString ) ;
2020-02-28 22:32:02 +00:00
var rows = searchResultDocument . QuerySelectorAll ( "table.lista > tbody > tr" ) ;
2015-07-26 03:48:18 +00:00
foreach ( var row in rows )
{
// this tracker has horrible markup, find the result rows by looking for the style tag before each one
var prev = row . PreviousElementSibling ;
2020-03-15 21:38:54 +00:00
if ( prev = = null | | ! string . Equals ( prev . NodeName , "style" , StringComparison . OrdinalIgnoreCase ) )
2020-02-09 02:35:16 +00:00
continue ;
2015-07-26 03:48:18 +00:00
2022-01-16 10:30:11 +00:00
var release = new ReleaseInfo
{
MinimumRatio = 1 ,
MinimumSeedTime = 86400 // 24 hours
} ;
2015-07-26 03:48:18 +00:00
2020-02-28 22:32:02 +00:00
var qLink = row . Children [ 1 ] . FirstElementChild ;
release . Title = qLink . TextContent . Trim ( ) ;
2020-11-08 02:11:27 +00:00
release . Details = new Uri ( SiteLink + qLink . GetAttribute ( "href" ) ) ;
release . Guid = release . Details ;
2015-07-26 03:48:18 +00:00
2020-03-15 21:38:54 +00:00
var imdbLink = row . Children [ 1 ] . QuerySelector ( "a[href*=imdb]" ) ;
2020-04-07 16:17:17 +00:00
if ( imdbLink ! = null )
2020-03-15 21:38:54 +00:00
release . Imdb = ParseUtil . GetImdbID ( imdbLink . GetAttribute ( "href" ) . Split ( '/' ) . Last ( ) ) ;
2020-04-07 16:17:17 +00:00
2020-02-28 22:32:02 +00:00
var qDownload = row . Children [ 3 ] . FirstElementChild ;
release . Link = new Uri ( SiteLink + qDownload . GetAttribute ( "href" ) ) ;
2015-07-26 03:48:18 +00:00
2020-02-28 22:32:02 +00:00
var dateStr = row . Children [ 4 ] . TextContent . Trim ( ) ;
//"July 11, 2015, 13:34:09", "Today|Yesterday at 20:04:23"
2020-03-15 21:38:54 +00:00
release . PublishDate = DateTimeUtil . FromUnknown ( dateStr ) ;
2020-02-28 22:32:02 +00:00
var sizeStr = row . Children [ 5 ] . TextContent ;
2015-07-26 03:48:18 +00:00
release . Size = ReleaseInfo . GetBytes ( sizeStr ) ;
2020-02-28 22:32:02 +00:00
release . Seeders = ParseUtil . CoerceInt ( row . Children [ 7 ] . TextContent ) ;
release . Peers = ParseUtil . CoerceInt ( row . Children [ 8 ] . TextContent ) + release . Seeders ;
var grabs = row . QuerySelector ( "td:nth-child(10)" ) . TextContent ;
2016-10-27 07:35:31 +00:00
grabs = grabs . Replace ( "---" , "0" ) ;
release . Grabs = ParseUtil . CoerceInt ( grabs ) ;
2020-02-28 22:32:02 +00:00
if ( row . QuerySelector ( "img[title=\"FreeLeech\"]" ) ! = null )
2017-04-15 08:45:10 +00:00
release . DownloadVolumeFactor = 0 ;
2020-02-28 22:32:02 +00:00
else if ( row . QuerySelector ( "img[src=\"images/sf.png\"]" ) ! = null ) // side freeleech
2017-04-15 08:45:10 +00:00
release . DownloadVolumeFactor = 0 ;
2020-02-28 22:32:02 +00:00
else if ( row . QuerySelector ( "img[title=\"Half FreeLeech\"]" ) ! = null )
2017-04-15 08:45:10 +00:00
release . DownloadVolumeFactor = 0.5 ;
2016-10-27 07:35:31 +00:00
else
release . DownloadVolumeFactor = 1 ;
release . UploadVolumeFactor = 1 ;
2020-02-28 22:32:02 +00:00
var qCat = row . QuerySelector ( "a[href^=\"index.php?page=torrents&category=\"]" ) ;
var cat = qCat . GetAttribute ( "href" ) . Split ( '=' ) [ 2 ] ;
2016-10-27 16:50:58 +00:00
release . Category = MapTrackerCatToNewznab ( cat ) ;
2015-07-26 03:48:18 +00:00
releases . Add ( release ) ;
}
}
catch ( Exception ex )
{
2020-06-09 17:36:57 +00:00
OnParseError ( response . ContentString , ex ) ;
2015-07-26 03:48:18 +00:00
}
2020-02-28 22:32:02 +00:00
2015-07-28 23:10:04 +00:00
return releases ;
2015-07-26 03:48:18 +00:00
}
}
}