2017-10-29 06:50:47 +00:00
using System ;
2015-07-30 20:09:38 +00:00
using System.Collections.Generic ;
using System.Collections.Specialized ;
using System.Globalization ;
using System.Text ;
using System.Threading.Tasks ;
2017-10-29 06:50:47 +00:00
using CsQuery ;
using Jackett.Models ;
2015-08-03 21:38:45 +00:00
using Jackett.Models.IndexerConfig ;
2017-10-29 10:19:09 +00:00
using Jackett.Services.Interfaces ;
2017-10-29 06:50:47 +00:00
using Jackett.Utils ;
using Jackett.Utils.Clients ;
using Newtonsoft.Json.Linq ;
using NLog ;
2015-07-30 20:09:38 +00:00
namespace Jackett.Indexers
{
2017-07-10 20:58:44 +00:00
public class TorrentBytes : BaseWebIndexer
2015-07-30 20:09:38 +00:00
{
private string BrowseUrl { get { return SiteLink + "browse.php" ; } }
private string LoginUrl { get { return SiteLink + "takelogin.php" ; } }
2017-10-29 06:50:47 +00:00
private new ConfigurationDataBasicLogin configData
2015-08-03 21:38:45 +00:00
{
get { return ( ConfigurationDataBasicLogin ) base . configData ; }
set { base . configData = value ; }
}
2017-11-05 09:42:03 +00:00
public TorrentBytes ( IIndexerConfigurationService configService , WebClient wc , Logger l , IProtectionService ps )
2015-07-30 20:09:38 +00:00
: base ( name : "TorrentBytes" ,
description : "A decade of torrentbytes" ,
link : "https://www.torrentbytes.net/" ,
2015-08-11 18:48:25 +00:00
caps : TorznabUtil . CreateDefaultTorznabTVCaps ( ) ,
2017-07-10 20:58:44 +00:00
configService : configService ,
2015-07-30 20:09:38 +00:00
client : wc ,
2015-08-03 21:38:45 +00:00
logger : l ,
2015-08-07 19:09:13 +00:00
p : ps ,
2017-07-27 21:49:20 +00:00
configData : new ConfigurationDataBasicLogin ( "For best results, change the 'Torrents per page' setting to 30 or greater (100 recommended) in your profile on the TorrentBytes webpage." ) )
2015-07-30 20:09:38 +00:00
{
2016-12-06 13:56:47 +00:00
Encoding = Encoding . GetEncoding ( "iso-8859-1" ) ;
2016-12-09 17:20:58 +00:00
Language = "en-us" ;
2017-01-28 06:07:44 +00:00
Type = "semi-private" ;
2015-08-03 21:38:45 +00:00
2015-07-30 20:09:38 +00:00
AddCategoryMapping ( 41 , TorznabCatType . TV ) ;
AddCategoryMapping ( 33 , TorznabCatType . TVSD ) ;
AddCategoryMapping ( 38 , TorznabCatType . TVHD ) ;
AddCategoryMapping ( 32 , TorznabCatType . TVSD ) ;
AddCategoryMapping ( 37 , TorznabCatType . TVSD ) ;
AddCategoryMapping ( 44 , TorznabCatType . TVSD ) ;
AddCategoryMapping ( 40 , TorznabCatType . Movies ) ;
AddCategoryMapping ( 19 , TorznabCatType . MoviesSD ) ;
AddCategoryMapping ( 5 , TorznabCatType . MoviesHD ) ;
AddCategoryMapping ( 20 , TorznabCatType . MoviesSD ) ;
AddCategoryMapping ( 28 , TorznabCatType . MoviesForeign ) ;
AddCategoryMapping ( 45 , TorznabCatType . MoviesSD ) ;
AddCategoryMapping ( 43 , TorznabCatType . Audio ) ;
AddCategoryMapping ( 48 , TorznabCatType . AudioLossless ) ;
2015-08-12 17:31:59 +00:00
AddCategoryMapping ( 6 , TorznabCatType . AudioMP3 ) ;
2015-07-30 20:09:38 +00:00
AddCategoryMapping ( 46 , TorznabCatType . Movies ) ;
2015-08-12 17:31:59 +00:00
AddCategoryMapping ( 1 , TorznabCatType . PC ) ;
AddCategoryMapping ( 2 , TorznabCatType . PC ) ;
AddCategoryMapping ( 23 , TorznabCatType . TVAnime ) ;
2015-07-30 20:09:38 +00:00
AddCategoryMapping ( 21 , TorznabCatType . XXX ) ;
2015-08-12 17:31:59 +00:00
AddCategoryMapping ( 9 , TorznabCatType . XXXXviD ) ;
AddCategoryMapping ( 39 , TorznabCatType . XXXx264 ) ;
AddCategoryMapping ( 29 , TorznabCatType . XXXXviD ) ;
AddCategoryMapping ( 24 , TorznabCatType . XXXImageset ) ;
2015-07-30 20:09:38 +00:00
}
2017-06-28 05:31:38 +00:00
public override async Task < IndexerConfigurationStatus > ApplyConfiguration ( JToken configJson )
2015-07-30 20:09:38 +00:00
{
2017-01-02 20:39:28 +00:00
LoadValuesFromJson ( configJson ) ;
2015-07-30 20:09:38 +00:00
var pairs = new Dictionary < string , string > {
2015-08-03 21:38:45 +00:00
{ "username" , configData . Username . Value } ,
{ "password" , configData . Password . Value } ,
2015-07-30 20:09:38 +00:00
{ "returnto" , "/" } ,
{ "login" , "Log in!" }
} ;
var loginPage = await RequestStringWithCookies ( SiteLink , string . Empty ) ;
var result = await RequestLoginAndFollowRedirect ( LoginUrl , pairs , loginPage . Cookies , true , SiteLink , SiteLink ) ;
2015-08-02 17:28:59 +00:00
await ConfigureIfOK ( result . Cookies , result . Content ! = null & & result . Content . Contains ( "logout.php" ) , ( ) = >
2015-07-30 20:09:38 +00:00
{
CQ dom = result . Content ;
2017-02-16 16:36:40 +00:00
var messageEl = dom [ "td.embedded" ] . First ( ) ;
var errorMessage = messageEl . Text ( ) ;
2017-04-15 08:45:10 +00:00
if ( string . IsNullOrWhiteSpace ( errorMessage ) )
errorMessage = result . Content ;
2015-08-03 21:38:45 +00:00
throw new ExceptionWithConfigData ( errorMessage , configData ) ;
2015-07-30 20:09:38 +00:00
} ) ;
2015-08-22 20:57:13 +00:00
return IndexerConfigurationStatus . RequiresTesting ;
2015-07-30 20:09:38 +00:00
}
2017-07-03 05:15:47 +00:00
protected override async Task < IEnumerable < ReleaseInfo > > PerformQuery ( TorznabQuery query )
2015-07-30 20:09:38 +00:00
{
var releases = new List < ReleaseInfo > ( ) ;
2015-08-14 21:20:51 +00:00
var searchString = query . GetQueryString ( ) ;
2015-07-30 20:09:38 +00:00
var searchUrl = BrowseUrl ;
var trackerCats = MapTorznabCapsToTrackers ( query ) ;
var queryCollection = new NameValueCollection ( ) ;
// Tracker can only search OR return things in categories
if ( ! string . IsNullOrWhiteSpace ( searchString ) )
{
queryCollection . Add ( "search" , searchString ) ;
queryCollection . Add ( "cat" , "0" ) ;
queryCollection . Add ( "sc" , "1" ) ;
}
else
{
foreach ( var cat in MapTorznabCapsToTrackers ( query ) )
{
queryCollection . Add ( "c" + cat , "1" ) ;
}
queryCollection . Add ( "incldead" , "0" ) ;
}
searchUrl + = "?" + queryCollection . GetQueryString ( ) ;
2015-08-03 21:38:45 +00:00
await ProcessPage ( releases , searchUrl ) ;
2015-07-30 20:09:38 +00:00
return releases ;
}
private async Task ProcessPage ( List < ReleaseInfo > releases , string searchUrl )
{
var response = await RequestStringWithCookiesAndRetry ( searchUrl , null , BrowseUrl ) ;
2016-11-06 16:41:22 +00:00
// On IP change the cookies become invalid, login again and retry
2017-04-15 08:45:10 +00:00
if ( response . IsRedirect )
{
await ApplyConfiguration ( null ) ;
response = await RequestStringWithCookiesAndRetry ( searchUrl , null , BrowseUrl ) ;
2016-11-06 16:41:22 +00:00
}
2015-07-30 20:09:38 +00:00
var results = response . Content ;
try
{
CQ dom = results ;
2016-10-25 07:41:30 +00:00
var rows = dom [ "table > tbody:has(tr > td.colhead) > tr:not(:has(td.colhead))" ] ;
foreach ( var row in rows )
2015-07-30 20:09:38 +00:00
{
var release = new ReleaseInfo ( ) ;
var link = row . Cq ( ) . Find ( "td:eq(1) a:eq(1)" ) . First ( ) ;
release . Guid = new Uri ( SiteLink + link . Attr ( "href" ) ) ;
release . Comments = release . Guid ;
2016-10-27 07:35:31 +00:00
release . Title = link . Get ( 0 ) . FirstChild . ToString ( ) ;
2015-07-30 20:09:38 +00:00
release . Description = release . Title ;
// If we search an get no results, we still get a table just with no info.
if ( string . IsNullOrWhiteSpace ( release . Title ) )
{
break ;
}
2016-01-19 13:20:19 +00:00
// Check if the release has been assigned a category
if ( row . Cq ( ) . Find ( "td:eq(0) a" ) . Length > 0 )
{
var cat = row . Cq ( ) . Find ( "td:eq(0) a" ) . First ( ) . Attr ( "href" ) . Substring ( 15 ) ;
release . Category = MapTrackerCatToNewznab ( cat ) ;
}
2015-07-30 20:09:38 +00:00
var qLink = row . Cq ( ) . Find ( "td:eq(1) a" ) . First ( ) ;
release . Link = new Uri ( SiteLink + qLink . Attr ( "href" ) ) ;
var added = row . Cq ( ) . Find ( "td:eq(4)" ) . First ( ) . Text ( ) . Trim ( ) ;
2017-08-05 00:45:38 +00:00
release . PublishDate = DateTime . ParseExact ( added , "yyyy-MM-ddHH:mm:ss" , CultureInfo . InvariantCulture ) ;
2015-07-30 20:09:38 +00:00
var sizeStr = row . Cq ( ) . Find ( "td:eq(6)" ) . First ( ) . Text ( ) . Trim ( ) ;
release . Size = ReleaseInfo . GetBytes ( sizeStr ) ;
release . Seeders = ParseUtil . CoerceInt ( row . Cq ( ) . Find ( "td:eq(8)" ) . First ( ) . Text ( ) . Trim ( ) ) ;
release . Peers = ParseUtil . CoerceInt ( row . Cq ( ) . Find ( "td:eq(9)" ) . First ( ) . Text ( ) . Trim ( ) ) + release . Seeders ;
2016-10-27 07:35:31 +00:00
var files = row . Cq ( ) . Find ( "td:nth-child(3)" ) . Text ( ) ;
release . Files = ParseUtil . CoerceInt ( files ) ;
var grabs = row . Cq ( ) . Find ( "td:nth-child(8)" ) . Text ( ) ;
if ( grabs ! = "----" )
release . Grabs = ParseUtil . CoerceInt ( grabs ) ;
2017-04-15 08:45:10 +00:00
if ( row . Cq ( ) . Find ( "font[color=\"green\"]:contains(F):contains(L)" ) . Length > = 1 )
release . DownloadVolumeFactor = 0 ;
2016-10-27 07:35:31 +00:00
else
2017-04-15 08:45:10 +00:00
release . DownloadVolumeFactor = 1 ;
2016-10-27 07:35:31 +00:00
release . UploadVolumeFactor = 1 ;
2015-07-30 20:09:38 +00:00
releases . Add ( release ) ;
}
}
catch ( Exception ex )
{
OnParseError ( results , ex ) ;
}
}
}
}