2017-10-29 06:50:47 +00:00
using System ;
using System.Collections.Generic ;
using System.Collections.Specialized ;
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
using CsQuery ;
2017-04-15 08:45:10 +00:00
using Jackett.Models ;
2017-10-29 06:50:47 +00:00
using Jackett.Models.IndexerConfig ;
2017-10-29 10:19:09 +00:00
using Jackett.Services.Interfaces ;
2017-04-15 08:45:10 +00:00
using Jackett.Utils ;
using Jackett.Utils.Clients ;
using Newtonsoft.Json.Linq ;
using NLog ;
namespace Jackett.Indexers
{
2017-07-10 20:58:44 +00:00
public class TorrentDay : BaseWebIndexer
2017-04-15 08:45:10 +00:00
{
private string StartPageUrl { get { return SiteLink + "login.php" ; } }
private string LoginUrl { get { return SiteLink + "tak3login.php" ; } }
private string SearchUrl { get { return SiteLink + "browse.php" ; } }
2017-10-29 06:50:47 +00:00
2017-08-31 08:50:47 +00:00
public override string [ ] AlternativeSiteLinks { get ; protected set ; } = new string [ ] {
2017-04-15 08:45:10 +00:00
"https://tdonline.org/" ,
"https://secure.torrentday.com/" ,
"https://torrentday.eu/" ,
"https://torrentday.it/" ,
"https://classic.torrentday.com/" ,
"https://www.torrentday.com/" ,
"https://td-update.com/" ,
"https://www.torrentday.me/" ,
"https://www.torrentday.ru/" ,
"https://www.torrentday.com/" ,
"https://www.td.af/" ,
} ;
2017-10-29 06:50:47 +00:00
private new ConfigurationDataRecaptchaLogin configData
2017-04-15 08:45:10 +00:00
{
get { return ( ConfigurationDataRecaptchaLogin ) base . configData ; }
set { base . configData = value ; }
}
2017-11-05 09:42:03 +00:00
public TorrentDay ( IIndexerConfigurationService configService , WebClient wc , Logger l , IProtectionService ps )
2017-04-15 08:45:10 +00:00
: base ( name : "TorrentDay" ,
2017-10-04 05:05:10 +00:00
description : "TorrentDay (TD) is a Private site for TV / MOVIES / GENERAL" ,
2017-04-15 08:45:10 +00:00
link : "https://torrentday.it/" ,
caps : TorznabUtil . CreateDefaultTorznabTVCaps ( ) ,
2017-07-10 20:58:44 +00:00
configService : configService ,
2017-04-15 08:45:10 +00:00
client : wc ,
logger : l ,
p : ps ,
configData : new ConfigurationDataRecaptchaLogin ( ) )
{
2017-11-05 09:42:03 +00:00
Encoding = Encoding . UTF8 ;
2017-04-15 08:45:10 +00:00
Language = "en-us" ;
Type = "private" ;
TorznabCaps . SupportsImdbSearch = true ;
2016-11-04 17:26:58 +00:00
AddCategoryMapping ( 29 , TorznabCatType . TVAnime ) ; // Anime
AddCategoryMapping ( 28 , TorznabCatType . PC ) ; // Appz/Packs
AddCategoryMapping ( 42 , TorznabCatType . AudioAudiobook ) ; // Audio Books
AddCategoryMapping ( 20 , TorznabCatType . Books ) ; // Books
AddCategoryMapping ( 30 , TorznabCatType . TVDocumentary ) ; // Documentary
AddCategoryMapping ( 47 , TorznabCatType . Other ) ; // Fonts
AddCategoryMapping ( 43 , TorznabCatType . PCMac ) ; // Mac
AddCategoryMapping ( 25 , TorznabCatType . MoviesSD ) ; // Movies/480p
AddCategoryMapping ( 11 , TorznabCatType . MoviesBluRay ) ; // Movies/Bluray
AddCategoryMapping ( 5 , TorznabCatType . MoviesBluRay ) ; // Movies/Bluray-Full
AddCategoryMapping ( 3 , TorznabCatType . MoviesDVD ) ; // Movies/DVD-R
AddCategoryMapping ( 21 , TorznabCatType . MoviesSD ) ; // Movies/MP4
AddCategoryMapping ( 22 , TorznabCatType . MoviesForeign ) ; // Movies/Non-English
AddCategoryMapping ( 13 , TorznabCatType . Movies ) ; // Movies/Packs
AddCategoryMapping ( 44 , TorznabCatType . MoviesSD ) ; // Movies/SD/x264
AddCategoryMapping ( 48 , TorznabCatType . MoviesHD ) ; // Movies/x265
AddCategoryMapping ( 1 , TorznabCatType . MoviesSD ) ; // Movies/XviD
AddCategoryMapping ( 23 , TorznabCatType . AudioForeign ) ; // Music/Non-English
AddCategoryMapping ( 41 , TorznabCatType . Audio ) ; // Music/Packs
AddCategoryMapping ( 16 , TorznabCatType . AudioVideo ) ; // Music/Video
AddCategoryMapping ( 45 , TorznabCatType . AudioOther ) ; // Podcast
AddCategoryMapping ( 4 , TorznabCatType . PCGames ) ; // PC/Games
AddCategoryMapping ( 18 , TorznabCatType . ConsolePS3 ) ; // PS3
AddCategoryMapping ( 8 , TorznabCatType . ConsolePSP ) ; // PSP
AddCategoryMapping ( 10 , TorznabCatType . ConsoleWii ) ; // Wii
AddCategoryMapping ( 9 , TorznabCatType . ConsoleXbox360 ) ; // Xbox-360
AddCategoryMapping ( 24 , TorznabCatType . TVSD ) ; // TV/480p
AddCategoryMapping ( 32 , TorznabCatType . TVHD ) ; // TV/Bluray
AddCategoryMapping ( 31 , TorznabCatType . TVSD ) ; // TV/DVD-R
AddCategoryMapping ( 33 , TorznabCatType . TVSD ) ; // TV/DVD-Rip
AddCategoryMapping ( 46 , TorznabCatType . TVSD ) ; // TV/Mobile
AddCategoryMapping ( 14 , TorznabCatType . TV ) ; // TV/Packs
AddCategoryMapping ( 26 , TorznabCatType . TVSD ) ; // TV/SD/x264
AddCategoryMapping ( 7 , TorznabCatType . TVHD ) ; // TV/x264
AddCategoryMapping ( 34 , TorznabCatType . TVHD ) ; // TV/x265
AddCategoryMapping ( 2 , TorznabCatType . TVSD ) ; // TV/XviD
AddCategoryMapping ( 6 , TorznabCatType . XXX ) ; // XXX/Movies
2017-04-15 08:45:10 +00:00
AddCategoryMapping ( 15 , TorznabCatType . XXXPacks ) ; // XXX/Packs
}
public override async Task < ConfigurationData > GetConfigurationForSetup ( )
{
var loginPage = await RequestStringWithCookies ( StartPageUrl , string . Empty ) ;
if ( loginPage . IsRedirect )
loginPage = await RequestStringWithCookies ( loginPage . RedirectingTo , string . Empty ) ;
if ( loginPage . IsRedirect )
loginPage = await RequestStringWithCookies ( loginPage . RedirectingTo , string . Empty ) ;
CQ cq = loginPage . Content ;
var result = this . configData ;
result . CookieHeader . Value = loginPage . Cookies ;
result . Captcha . SiteKey = cq . Find ( ".g-recaptcha" ) . Attr ( "data-sitekey" ) ;
result . Captcha . Version = "2" ;
return result ;
}
2017-06-28 05:31:38 +00:00
public override async Task < IndexerConfigurationStatus > ApplyConfiguration ( JToken configJson )
2017-04-15 08:45:10 +00:00
{
LoadValuesFromJson ( configJson ) ;
var pairs = new Dictionary < string , string > {
{ "username" , configData . Username . Value } ,
{ "password" , configData . Password . Value } ,
{ "g-recaptcha-response" , configData . Captcha . Value }
} ;
if ( ! string . IsNullOrWhiteSpace ( configData . Captcha . Cookie ) )
{
// Cookie was manually supplied
CookieHeader = configData . Captcha . Cookie ;
try
{
var results = await PerformQuery ( new TorznabQuery ( ) ) ;
if ( results . Count ( ) = = 0 )
{
throw new Exception ( "Your cookie did not work" ) ;
}
IsConfigured = true ;
2017-05-06 17:39:02 +00:00
SaveConfig ( ) ;
2017-04-15 08:45:10 +00:00
return IndexerConfigurationStatus . Completed ;
}
catch ( Exception e )
{
IsConfigured = false ;
throw new Exception ( "Your cookie did not work: " + e . Message ) ;
}
}
2017-06-25 16:15:12 +00:00
var result = await RequestLoginAndFollowRedirect ( LoginUrl , pairs , configData . CookieHeader . Value , true , null , LoginUrl ) ;
2017-04-15 08:45:10 +00:00
await ConfigureIfOK ( result . Cookies , result . Content ! = null & & result . Content . Contains ( "logout.php" ) , ( ) = >
{
CQ dom = result . Content ;
var messageEl = dom [ "#login" ] ;
messageEl . Children ( "form" ) . Remove ( ) ;
var errorMessage = messageEl . Text ( ) . Trim ( ) ;
if ( string . IsNullOrWhiteSpace ( errorMessage ) )
{
errorMessage = dom . Text ( ) ;
}
if ( string . IsNullOrWhiteSpace ( errorMessage ) & & result . IsRedirect )
{
errorMessage = string . Format ( "Got a redirect to {0}, please adjust your the alternative link" , result . RedirectingTo ) ;
}
throw new ExceptionWithConfigData ( errorMessage , configData ) ;
} ) ;
return IndexerConfigurationStatus . RequiresTesting ;
}
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
{
var releases = new List < ReleaseInfo > ( ) ;
var searchString = query . GetQueryString ( ) ;
var queryUrl = SearchUrl ;
var queryCollection = new NameValueCollection ( ) ;
if ( ! string . IsNullOrWhiteSpace ( query . ImdbID ) & & query . ImdbID . ToLower ( ) . StartsWith ( "tt" ) )
{
queryCollection . Add ( "search" , query . ImdbID ) ;
}
else
{
if ( ! string . IsNullOrWhiteSpace ( searchString ) )
queryCollection . Add ( "search" , searchString ) ;
}
foreach ( var cat in MapTorznabCapsToTrackers ( query ) )
queryCollection . Add ( "c" + cat , "1" ) ;
if ( queryCollection . Count > 0 )
queryUrl + = "?" + queryCollection . GetQueryString ( ) ;
var results = await RequestStringWithCookiesAndRetry ( queryUrl ) ;
// Check for being logged out
if ( results . IsRedirect )
if ( results . RedirectingTo . Contains ( "login.php" ) )
throw new ExceptionWithConfigData ( "Login failed, please reconfigure the tracker to update the cookies" , configData ) ;
else
throw new ExceptionWithConfigData ( string . Format ( "Got a redirect to {0}, please adjust your the alternative link" , results . RedirectingTo ) , configData ) ;
try
{
CQ dom = results . Content ;
2018-01-29 18:38:19 +00:00
var rows = dom [ "#torrentTable > tbody > tr[id^=tr]" ] ; //handy browse class has gone, use basic tr selector instead but filter for rows with an id beginning "tr"
2017-04-15 08:45:10 +00:00
foreach ( var row in rows )
{
CQ qRow = row . Cq ( ) ;
var release = new ReleaseInfo ( ) ;
release . MinimumRatio = 1 ;
release . MinimumSeedTime = 172800 ;
2018-01-29 18:38:19 +00:00
release . Title = qRow . Find ( ".torrentNameInfo > a" ) . Text ( ) ; //torrentName renamed to torrentNameInfo
2017-04-15 08:45:10 +00:00
if ( ( query . ImdbID = = null | | ! TorznabCaps . SupportsImdbSearch ) & & ! query . MatchQueryStringAND ( release . Title ) )
continue ;
2018-01-29 18:38:19 +00:00
release . Guid = new Uri ( SiteLink + qRow . Find ( ".torrentNameInfo > a" ) . Attr ( "href" ) ) ; //torrentName renamed to torrentNameInfo
2017-04-15 08:45:10 +00:00
release . Comments = release . Guid ;
2018-01-29 18:38:19 +00:00
release . Link = new Uri ( SiteLink + qRow . Find ( "td:eq(2) > a" ) . Attr ( "href" ) ) ; //download button doesnt have class anymore so use index selector instead
2017-04-15 08:45:10 +00:00
var sizeStr = qRow . Find ( ".sizeInfo" ) . Text ( ) ;
release . Size = ReleaseInfo . GetBytes ( sizeStr ) ;
var dateStr = qRow . Find ( ".ulInfo" ) . Text ( ) . Split ( '|' ) . Last ( ) . Trim ( ) ;
var agoIdx = dateStr . IndexOf ( "ago" ) ;
if ( agoIdx > - 1 )
{
dateStr = dateStr . Substring ( 0 , agoIdx ) ;
}
release . PublishDate = DateTimeUtil . FromTimeAgo ( dateStr ) ;
release . Seeders = ParseUtil . CoerceInt ( qRow . Find ( ".seedersInfo" ) . Text ( ) ) ;
release . Peers = ParseUtil . CoerceInt ( qRow . Find ( ".leechersInfo" ) . Text ( ) ) + release . Seeders ;
2018-01-29 18:38:19 +00:00
//category number is stored in the id of the anchor now... it makes no sense to me either but thats how it is
var cat = qRow . Find ( "td:eq(0) a" ) . First ( ) . Attr ( "id" ) ;
2017-04-15 08:45:10 +00:00
release . Category = MapTrackerCatToNewznab ( cat ) ;
if ( qRow . Find ( "span.flTags" ) . 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 ;
release . UploadVolumeFactor = 1 ;
releases . Add ( release ) ;
}
}
catch ( Exception ex )
{
OnParseError ( results . Content , ex ) ;
}
return releases ;
}
}
}