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 ;
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:50:47 +00:00
using Newtonsoft.Json.Linq ;
using NLog ;
2015-07-30 20:09:38 +00:00
2018-03-10 08:05:56 +00:00
namespace Jackett.Common.Indexers
2015-07-30 20:09:38 +00:00
{
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-12-17 19:26:35 +00:00
Type = "private" ;
2015-08-03 21:38:45 +00:00
2018-01-14 19:47:21 +00:00
AddCategoryMapping ( 23 , TorznabCatType . TVAnime , "Anime" ) ;
AddCategoryMapping ( 52 , TorznabCatType . PCMac , "Apple/All" ) ;
AddCategoryMapping ( 22 , TorznabCatType . PC , "Apps/misc" ) ;
AddCategoryMapping ( 1 , TorznabCatType . PC , "Apps/PC" ) ;
AddCategoryMapping ( 28 , TorznabCatType . TVFOREIGN , "Foreign Titles" ) ;
AddCategoryMapping ( 50 , TorznabCatType . Console , "Games/Consoles" ) ;
AddCategoryMapping ( 42 , TorznabCatType . PCGames , "Games/Pack" ) ;
AddCategoryMapping ( 4 , TorznabCatType . PCGames , "Games/PC" ) ;
AddCategoryMapping ( 51 , TorznabCatType . PC , "Linux/All" ) ;
AddCategoryMapping ( 31 , TorznabCatType . OtherMisc , "Misc" ) ;
AddCategoryMapping ( 20 , TorznabCatType . MoviesDVD , "Movies/DVD-R" ) ;
AddCategoryMapping ( 12 , TorznabCatType . MoviesBluRay , "Movies/Full Blu-ray" ) ;
AddCategoryMapping ( 5 , TorznabCatType . MoviesHD , "Movies/HD" ) ;
AddCategoryMapping ( 40 , TorznabCatType . Movies , "Movies/Pack" ) ;
AddCategoryMapping ( 19 , TorznabCatType . MoviesSD , "Movies/SD" ) ;
AddCategoryMapping ( 49 , TorznabCatType . MoviesUHD , "Movies/UHD" ) ;
AddCategoryMapping ( 25 , TorznabCatType . Audio , "Music/DVDR" ) ;
AddCategoryMapping ( 48 , TorznabCatType . AudioLossless , "Music/Flac" ) ;
AddCategoryMapping ( 6 , TorznabCatType . AudioMP3 , "Music/MP3" ) ;
AddCategoryMapping ( 43 , TorznabCatType . Audio , "Music/Pack" ) ;
AddCategoryMapping ( 34 , TorznabCatType . AudioVideo , "Music/Videos" ) ;
AddCategoryMapping ( 45 , TorznabCatType . MoviesBluRay , "NonScene/BRrip" ) ;
AddCategoryMapping ( 46 , TorznabCatType . MoviesHD , "NonScene/x264" ) ;
AddCategoryMapping ( 44 , TorznabCatType . MoviesSD , "NonScene/Xvid" ) ;
AddCategoryMapping ( 37 , TorznabCatType . TVHD , "TV/BRrip" ) ;
AddCategoryMapping ( 38 , TorznabCatType . TVHD , "TV/HD" ) ;
AddCategoryMapping ( 41 , TorznabCatType . TV , "TV/Pack" ) ;
AddCategoryMapping ( 33 , TorznabCatType . TVSD , "TV/SD" ) ;
AddCategoryMapping ( 32 , TorznabCatType . TVUHD , "TV/UHD" ) ;
AddCategoryMapping ( 39 , TorznabCatType . XXXx264 , "XXX/HD" ) ;
AddCategoryMapping ( 24 , TorznabCatType . XXXImageset , "XXX/IMGSET" ) ;
AddCategoryMapping ( 21 , TorznabCatType . XXXPacks , "XXX/Pack" ) ;
AddCategoryMapping ( 9 , TorznabCatType . XXXXviD , "XXX/SD" ) ;
AddCategoryMapping ( 29 , TorznabCatType . XXX , "XXX/Web" ) ;
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 ) ;
2018-05-18 16:10:32 +00:00
await ConfigureIfOK ( result . Cookies , result . Content ! = null & & result . Content . Contains ( "my.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 ) ;
}
}
}
}