2015-04-26 02:32:03 +00:00
using CsQuery ;
2015-07-19 00:27:41 +00:00
using Jackett.Models ;
2015-07-19 17:18:54 +00:00
using Jackett.Services ;
2015-07-19 00:27:41 +00:00
using Jackett.Utils ;
2015-07-27 00:03:51 +00:00
using Jackett.Utils.Clients ;
2015-04-26 02:32:03 +00:00
using Newtonsoft.Json.Linq ;
2015-07-19 00:27:41 +00:00
using NLog ;
2015-04-26 02:32:03 +00:00
using System ;
using System.Collections.Generic ;
using System.Globalization ;
using System.Linq ;
using System.Net ;
using System.Net.Http ;
using System.Text ;
using System.Threading.Tasks ;
using System.Web ;
2015-08-03 21:38:45 +00:00
using Jackett.Models.IndexerConfig ;
2015-04-26 02:32:03 +00:00
namespace Jackett.Indexers
{
2015-07-19 17:18:54 +00:00
public class TorrentLeech : BaseIndexer , IIndexer
2015-04-26 02:32:03 +00:00
{
2015-07-27 00:03:51 +00:00
private string LoginUrl { get { return SiteLink + "user/account/login/" ; } }
2015-08-13 21:51:49 +00:00
private string SearchUrl { get { return SiteLink + "torrents/browse/index/" ; } }
2015-04-26 02:32:03 +00:00
2015-08-03 21:38:45 +00:00
new ConfigurationDataBasicLogin configData
{
get { return ( ConfigurationDataBasicLogin ) base . configData ; }
set { base . configData = value ; }
}
2015-08-07 19:09:13 +00:00
public TorrentLeech ( IIndexerManagerService i , Logger l , IWebClient wc , IProtectionService ps )
2015-07-19 23:05:30 +00:00
: base ( name : "TorrentLeech" ,
description : "This is what happens when you seed" ,
2015-10-07 23:17:54 +00:00
link : "https://www.torrentleech.org/" ,
2015-08-11 18:48:25 +00:00
caps : TorznabUtil . CreateDefaultTorznabTVCaps ( ) ,
2015-07-19 23:05:30 +00:00
manager : i ,
2015-07-27 00:03:51 +00:00
client : wc ,
2015-08-03 21:38:45 +00:00
logger : l ,
2015-08-07 19:09:13 +00:00
p : ps ,
2015-10-07 23:17:54 +00:00
downloadBase : "https://www.torrentleech.org/download/" ,
2016-08-22 10:47:36 +00:00
configData : new ConfigurationDataBasicLogin ( "For best results, change the 'Default Number of Torrents per Page' setting to the maximum in your profile on the TorrentLeech webpage." ) )
2015-04-26 02:32:03 +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" ;
2015-08-13 21:51:49 +00:00
AddCategoryMapping ( 8 , TorznabCatType . MoviesSD ) ; // cam
AddCategoryMapping ( 9 , TorznabCatType . MoviesSD ) ; //ts
AddCategoryMapping ( 10 , TorznabCatType . MoviesSD ) ; // Sceener
AddCategoryMapping ( 11 , TorznabCatType . MoviesSD ) ;
AddCategoryMapping ( 12 , TorznabCatType . MoviesSD ) ;
AddCategoryMapping ( 13 , TorznabCatType . MoviesHD ) ;
AddCategoryMapping ( 14 , TorznabCatType . MoviesHD ) ;
AddCategoryMapping ( 15 , TorznabCatType . Movies ) ; // Boxsets
AddCategoryMapping ( 29 , TorznabCatType . TVDocumentary ) ;
2016-12-11 15:36:48 +00:00
AddCategoryMapping ( 41 , TorznabCatType . MoviesHD ) ;
2015-08-13 21:51:49 +00:00
AddCategoryMapping ( 26 , TorznabCatType . TVSD ) ;
AddCategoryMapping ( 27 , TorznabCatType . TV ) ; // Boxsets
AddCategoryMapping ( 32 , TorznabCatType . TVHD ) ;
AddCategoryMapping ( 17 , TorznabCatType . PCGames ) ;
AddCategoryMapping ( 18 , TorznabCatType . ConsoleXbox ) ;
AddCategoryMapping ( 19 , TorznabCatType . ConsoleXbox360 ) ;
// 20 PS2
AddCategoryMapping ( 21 , TorznabCatType . ConsolePS3 ) ;
AddCategoryMapping ( 22 , TorznabCatType . ConsolePSP ) ;
AddCategoryMapping ( 28 , TorznabCatType . ConsoleWii ) ;
AddCategoryMapping ( 30 , TorznabCatType . ConsoleNDS ) ;
AddCategoryMapping ( 16 , TorznabCatType . AudioVideo ) ;
AddCategoryMapping ( 31 , TorznabCatType . Audio ) ;
AddCategoryMapping ( 34 , TorznabCatType . TVAnime ) ;
AddCategoryMapping ( 35 , TorznabCatType . TV ) ; // Cartoons
AddCategoryMapping ( 5 , TorznabCatType . Books ) ;
AddCategoryMapping ( 23 , TorznabCatType . PCISO ) ;
AddCategoryMapping ( 24 , TorznabCatType . PCMac ) ;
AddCategoryMapping ( 25 , TorznabCatType . PCPhoneOther ) ;
AddCategoryMapping ( 33 , TorznabCatType . PC0day ) ;
2015-04-26 02:32:03 +00:00
}
2015-08-22 20:57:13 +00:00
public async Task < IndexerConfigurationStatus > ApplyConfiguration ( JToken configJson )
2015-04-26 02:32:03 +00:00
{
2015-08-03 21:38:45 +00:00
configData . LoadValuesFromJson ( configJson ) ;
2016-08-05 11:57:43 +00:00
await DoLogin ( ) ;
return IndexerConfigurationStatus . RequiresTesting ;
}
private async Task DoLogin ( )
{
2015-04-26 02:32:03 +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-04-26 02:32:03 +00:00
{ "remember_me" , "on" } ,
{ "login" , "submit" }
2015-08-03 21:38:45 +00:00
} ;
2015-04-26 02:32:03 +00:00
2015-08-03 21:38:45 +00:00
var result = await RequestLoginAndFollowRedirect ( LoginUrl , pairs , null , true , null , LoginUrl ) ;
2015-08-02 17:28:59 +00:00
await ConfigureIfOK ( result . Cookies , result . Content ! = null & & result . Content . Contains ( "/user/account/logout" ) , ( ) = >
2015-04-26 02:32:03 +00:00
{
2015-07-27 00:03:51 +00:00
CQ dom = result . Content ;
2015-04-26 02:32:03 +00:00
var messageEl = dom [ ".ui-state-error" ] . Last ( ) ;
var errorMessage = messageEl . Text ( ) . Trim ( ) ;
2015-08-03 21:38:45 +00:00
throw new ExceptionWithConfigData ( errorMessage , configData ) ;
2015-07-27 00:03:51 +00:00
} ) ;
2015-04-26 02:32:03 +00:00
}
2015-07-28 23:10:04 +00:00
public async Task < IEnumerable < ReleaseInfo > > PerformQuery ( TorznabQuery query )
2015-04-26 02:32:03 +00:00
{
2016-08-05 11:57:43 +00:00
var loggedInCheck = await RequestStringWithCookies ( SearchUrl ) ;
if ( ! loggedInCheck . Content . Contains ( "/logout.php" ) )
{
//Cookie appears to expire after a period of time or logging in to the site via browser
await DoLogin ( ) ;
}
2015-07-28 23:10:04 +00:00
var releases = new List < ReleaseInfo > ( ) ;
2016-10-25 06:46:06 +00:00
var searchString = query . GetQueryString ( ) ;
searchString = searchString . Replace ( '-' , ' ' ) ; // remove dashes as they exclude search strings
2015-08-13 21:51:49 +00:00
var searchUrl = SearchUrl ;
if ( ! string . IsNullOrWhiteSpace ( searchString ) )
{
2015-08-22 20:57:13 +00:00
searchUrl + = "query/" + HttpUtility . UrlEncode ( searchString ) + "/" ;
2015-08-13 21:51:49 +00:00
}
string . Format ( SearchUrl , HttpUtility . UrlEncode ( searchString ) ) ;
var cats = MapTorznabCapsToTrackers ( query ) ;
if ( cats . Count > 0 )
{
searchUrl + = "categories/" ;
foreach ( var cat in cats )
{
if ( ! searchUrl . EndsWith ( "/" ) )
searchUrl + = "," ;
searchUrl + = cat ;
}
2016-12-05 14:31:17 +00:00
}
else
{
searchUrl + = "newfilter/2" ; // include 0day and music
2015-08-13 21:51:49 +00:00
}
var results = await RequestStringWithCookiesAndRetry ( searchUrl ) ;
2015-07-18 20:35:02 +00:00
try
2015-04-26 02:32:03 +00:00
{
2015-07-27 00:03:51 +00:00
CQ dom = results . Content ;
2015-04-26 02:32:03 +00:00
2015-07-18 20:35:02 +00:00
CQ qRows = dom [ "#torrenttable > tbody > tr" ] ;
2015-04-26 02:32:03 +00:00
2015-07-18 20:35:02 +00:00
foreach ( var row in qRows )
{
var release = new ReleaseInfo ( ) ;
2015-04-26 02:32:03 +00:00
2015-07-18 20:35:02 +00:00
var qRow = row . Cq ( ) ;
2015-04-26 02:32:03 +00:00
2015-07-18 20:35:02 +00:00
var debug = qRow . Html ( ) ;
2015-04-26 02:32:03 +00:00
2015-07-18 20:35:02 +00:00
release . MinimumRatio = 1 ;
release . MinimumSeedTime = 172800 ;
2015-04-26 02:32:03 +00:00
2015-07-18 20:35:02 +00:00
CQ qLink = qRow . Find ( ".title > a" ) . First ( ) ;
2015-08-13 21:51:49 +00:00
release . Guid = new Uri ( SiteLink + qLink . Attr ( "href" ) . Substring ( 1 ) ) ;
2015-07-18 20:35:02 +00:00
release . Comments = release . Guid ;
release . Title = qLink . Text ( ) ;
release . Description = release . Title ;
2015-04-26 02:32:03 +00:00
2015-08-13 21:51:49 +00:00
release . Link = new Uri ( SiteLink + qRow . Find ( ".quickdownload > a" ) . Attr ( "href" ) . Substring ( 1 ) ) ;
2015-04-26 02:32:03 +00:00
2016-12-11 15:36:48 +00:00
var dateString = qRow . Find ( ".name" ) . Get ( 0 ) . LastChild . NodeValue . Replace ( "on" , string . Empty ) . Trim ( ) ; ;
release . PublishDate = DateTime . ParseExact ( dateString , "yyyy-MM-dd HH:mm:ss" , CultureInfo . InvariantCulture ) ;
2015-04-26 02:32:03 +00:00
2015-07-26 03:53:53 +00:00
var sizeStr = qRow . Children ( ) . ElementAt ( 4 ) . InnerText ;
release . Size = ReleaseInfo . GetBytes ( sizeStr ) ;
2015-04-26 02:32:03 +00:00
2015-07-18 20:35:02 +00:00
release . Seeders = ParseUtil . CoerceInt ( qRow . Find ( ".seeders" ) . Text ( ) ) ;
release . Peers = release . Seeders + ParseUtil . CoerceInt ( qRow . Find ( ".leechers" ) . Text ( ) ) ;
2015-05-04 04:12:14 +00:00
2015-08-22 20:57:13 +00:00
var category = qRow . Find ( ".category a" ) . Attr ( "href" ) . Replace ( "/torrents/browse/index/categories/" , string . Empty ) ;
2015-08-13 21:51:49 +00:00
release . Category = MapTrackerCatToNewznab ( category ) ;
2016-10-30 12:21:32 +00:00
var grabs = qRow . Find ( "td:nth-child(6)" ) . Get ( 0 ) . FirstChild . ToString ( ) ;
2016-10-27 07:35:31 +00:00
release . Grabs = ParseUtil . CoerceInt ( grabs ) ;
release . DownloadVolumeFactor = 1 ;
release . UploadVolumeFactor = 1 ;
2015-07-18 20:35:02 +00:00
releases . Add ( release ) ;
2015-04-26 02:32:03 +00:00
}
}
2015-07-18 20:35:02 +00:00
catch ( Exception ex )
{
2015-07-27 00:03:51 +00:00
OnParseError ( results . Content , ex ) ;
2015-07-18 20:35:02 +00:00
}
2015-05-04 04:12:14 +00:00
2015-07-28 23:10:04 +00:00
return releases ;
2015-04-26 02:32:03 +00:00
}
}
}