2017-10-29 06:50:47 +00:00
using System ;
2015-07-19 02:19:09 +00:00
using System.Collections.Generic ;
2017-10-29 06:50:47 +00:00
using System.Collections.Specialized ;
2015-07-19 02:19:09 +00:00
using System.Globalization ;
2016-01-19 13:08:00 +00:00
using System.Linq ;
2016-12-09 17:20:58 +00:00
using System.Text ;
2015-07-19 02:19:09 +00:00
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-19 02:19:09 +00:00
2018-03-10 08:05:56 +00:00
namespace Jackett.Common.Indexers
2015-07-19 02:19:09 +00:00
{
2017-07-10 20:58:44 +00:00
public class SpeedCD : BaseWebIndexer
2015-07-19 02:19:09 +00:00
{
2018-12-21 17:25:24 +00:00
private string LoginUrl { get { return SiteLink + "takelogin.php" ; } }
2016-01-19 13:08:00 +00:00
private string SearchUrl { get { return SiteLink + "browse.php" ; } }
2015-08-03 21:38:45 +00:00
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 SpeedCD ( IIndexerConfigurationService configService , WebClient wc , Logger l , IProtectionService ps )
2015-07-19 23:05:30 +00:00
: base ( name : "Speed.cd" ,
description : "Your home now!" ,
2016-01-19 13:08:00 +00:00
link : "https://speed.cd/" ,
2015-12-09 08:45:44 +00:00
caps : new TorznabCapabilities ( ) ,
2017-07-10 20:58:44 +00:00
configService : configService ,
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 ,
2016-07-27 04:14:57 +00:00
configData : new ConfigurationDataBasicLogin ( @ "Speed.Cd have increased their security. If you are having problems please check the security tab in your Speed.Cd profile.
eg . Geo Locking , your seedbox may be in a different country to the one where you login via your web browser "))
2015-07-19 02:19:09 +00:00
{
2016-12-09 17:20:58 +00:00
Encoding = Encoding . UTF8 ;
Language = "en-us" ;
2017-01-27 15:57:32 +00:00
Type = "private" ;
2016-12-09 17:20:58 +00:00
2017-02-24 18:13:55 +00:00
TorznabCaps . SupportsImdbSearch = true ;
2019-02-11 23:58:20 +00:00
AddCategoryMapping ( 1 , TorznabCatType . MoviesOther , "Movies/XviD" ) ;
AddCategoryMapping ( 42 , TorznabCatType . Movies , "Movies/Packs" ) ;
AddCategoryMapping ( 32 , TorznabCatType . Movies , "Movies/Kids" ) ;
AddCategoryMapping ( 43 , TorznabCatType . MoviesHD , "Movies/HD" ) ;
AddCategoryMapping ( 47 , TorznabCatType . Movies , "Movies/DiVERSiTY" ) ;
AddCategoryMapping ( 28 , TorznabCatType . MoviesBluRay , "Movies/B-Ray" ) ;
AddCategoryMapping ( 48 , TorznabCatType . Movies3D , "Movies/3D" ) ;
AddCategoryMapping ( 40 , TorznabCatType . MoviesDVD , "Movies/DVD-R" ) ;
AddCategoryMapping ( 56 , TorznabCatType . Movies , "Movies/Anime" ) ;
AddCategoryMapping ( 50 , TorznabCatType . TVSport , "TV/Sports" ) ;
AddCategoryMapping ( 52 , TorznabCatType . TVHD , "TV/B-Ray" ) ;
AddCategoryMapping ( 53 , TorznabCatType . TVSD , "TV/DVD-R" ) ;
AddCategoryMapping ( 41 , TorznabCatType . TV , "TV/Packs" ) ;
AddCategoryMapping ( 55 , TorznabCatType . TV , "TV/Kids" ) ;
AddCategoryMapping ( 57 , TorznabCatType . TV , "TV/DiVERSiTY" ) ;
AddCategoryMapping ( 49 , TorznabCatType . TVHD , "TV/HD" ) ;
AddCategoryMapping ( 2 , TorznabCatType . TVSD , "TV/Episodes" ) ;
AddCategoryMapping ( 30 , TorznabCatType . TVAnime , "TV/Anime" ) ;
AddCategoryMapping ( 25 , TorznabCatType . PCISO , "Games/PC ISO" ) ;
AddCategoryMapping ( 39 , TorznabCatType . ConsoleWii , "Games/Wii" ) ;
AddCategoryMapping ( 45 , TorznabCatType . ConsolePS3 , "Games/PS3" ) ;
AddCategoryMapping ( 35 , TorznabCatType . Console , "Games/Nintendo" ) ;
AddCategoryMapping ( 33 , TorznabCatType . ConsoleXbox360 , "Games/XboX360" ) ;
AddCategoryMapping ( 46 , TorznabCatType . PCPhoneOther , "Mobile" ) ;
AddCategoryMapping ( 24 , TorznabCatType . PC0day , "Apps/0DAY" ) ;
AddCategoryMapping ( 51 , TorznabCatType . PCMac , "Mac" ) ;
AddCategoryMapping ( 54 , TorznabCatType . Books , "Educational" ) ;
AddCategoryMapping ( 27 , TorznabCatType . Books , "Books-Mags" ) ;
AddCategoryMapping ( 26 , TorznabCatType . Audio , "Music/Audio" ) ;
AddCategoryMapping ( 44 , TorznabCatType . Audio , "Music/Pack" ) ;
AddCategoryMapping ( 29 , TorznabCatType . AudioVideo , "Music/Video" ) ;
2015-07-19 02:19:09 +00:00
}
2017-06-28 05:31:38 +00:00
public override async Task < IndexerConfigurationStatus > ApplyConfiguration ( JToken configJson )
2015-07-19 02:19:09 +00:00
{
2017-01-02 20:39:28 +00:00
LoadValuesFromJson ( configJson ) ;
2016-05-28 09:40:39 +00:00
await DoLogin ( ) ;
return IndexerConfigurationStatus . RequiresTesting ;
}
private async Task DoLogin ( )
{
2015-07-19 02:19:09 +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-19 02:19:09 +00:00
2015-08-02 18:14:21 +00:00
var result = await RequestLoginAndFollowRedirect ( LoginUrl , pairs , null , true , null , SiteLink ) ;
2016-05-28 09:40:39 +00:00
2016-07-27 04:14:57 +00:00
await ConfigureIfOK ( result . Cookies , result . Content ! = null & & result . Content . Contains ( "/browse.php" ) , ( ) = >
2015-07-19 02:19:09 +00:00
{
2015-07-27 00:03:51 +00:00
CQ dom = result . Content ;
2016-07-27 04:14:57 +00:00
var errorMessage = dom . Text ( ) ;
2019-01-16 11:26:43 +00:00
if ( errorMessage . Contains ( "Wrong Captcha!" ) )
errorMessage = "Captcha requiered due to a failed login attempt. Login via a browser to whitelist your IP and then reconfigure jackett." ;
2015-08-03 21:38:45 +00:00
throw new ExceptionWithConfigData ( errorMessage , configData ) ;
2015-07-27 00:03:51 +00:00
} ) ;
2015-07-19 02:19:09 +00:00
}
2017-07-03 05:15:47 +00:00
protected override async Task < IEnumerable < ReleaseInfo > > PerformQuery ( TorznabQuery query )
2015-07-19 02:19:09 +00:00
{
2015-07-27 00:03:51 +00:00
var releases = new List < ReleaseInfo > ( ) ;
2015-12-09 08:45:44 +00:00
2016-01-19 13:08:00 +00:00
NameValueCollection qParams = new NameValueCollection ( ) ;
2015-12-09 08:45:44 +00:00
2017-02-24 18:13:55 +00:00
if ( ! string . IsNullOrWhiteSpace ( query . ImdbID ) )
{
qParams . Add ( "search" , query . ImdbID ) ;
qParams . Add ( "d" , "on" ) ;
}
else if ( ! string . IsNullOrEmpty ( query . GetQueryString ( ) ) )
2015-12-09 08:45:44 +00:00
{
2016-01-20 08:45:39 +00:00
qParams . Add ( "search" , query . GetQueryString ( ) ) ;
2015-12-09 08:45:44 +00:00
}
List < string > catList = MapTorznabCapsToTrackers ( query ) ;
foreach ( string cat in catList )
{
qParams . Add ( "c" + cat , "1" ) ;
}
2016-01-19 13:08:00 +00:00
string urlSearch = SearchUrl ;
if ( qParams . Count > 0 )
2015-07-19 02:19:09 +00:00
{
2016-01-19 13:08:00 +00:00
urlSearch + = $"?{qParams.GetQueryString()}" ;
}
2015-07-19 02:19:09 +00:00
2016-01-19 13:08:00 +00:00
var response = await RequestStringWithCookiesAndRetry ( urlSearch ) ;
2017-02-24 18:13:55 +00:00
if ( ! response . Content . Contains ( "/logout.php" ) )
{
//Cookie appears to expire after a period of time or logging in to the site via browser
await DoLogin ( ) ;
response = await RequestStringWithCookiesAndRetry ( urlSearch ) ;
}
2015-07-19 02:19:09 +00:00
2016-01-19 13:08:00 +00:00
try
{
CQ dom = response . Content ;
2017-09-11 08:50:23 +00:00
var rows = dom [ "div[id='torrentTable'] > div[class^='box torrentBox'] > div[class='boxContent'] > table > tbody > tr" ] ;
2015-07-19 02:19:09 +00:00
2016-01-19 13:08:00 +00:00
foreach ( IDomObject row in rows )
{
CQ torrentData = row . OuterHTML ;
CQ cells = row . Cq ( ) . Find ( "td" ) ;
2018-08-29 10:26:48 +00:00
string title = torrentData . Find ( "td[class='lft'] > div > a" ) . First ( ) . Text ( ) . Trim ( ) ;
Uri link = new Uri ( SiteLink + torrentData . Find ( "img[title='Download']" ) . First ( ) . Parent ( ) . Attr ( "href" ) . Trim ( ) ) ;
Uri guid = link ;
2019-02-12 00:31:06 +00:00
Uri comments = new Uri ( SiteLink + torrentData . Find ( "td[class='lft'] > div > a" ) . First ( ) . Attr ( "href" ) . Trim ( ) . Remove ( 0 , 1 ) ) ;
2016-01-20 08:45:39 +00:00
long size = ReleaseInfo . GetBytes ( cells . Elements . ElementAt ( 4 ) . Cq ( ) . Text ( ) ) ;
2018-08-29 10:26:48 +00:00
int grabs = ParseUtil . CoerceInt ( cells . Elements . ElementAt ( 5 ) . Cq ( ) . Text ( ) ) ;
int seeders = ParseUtil . CoerceInt ( cells . Elements . ElementAt ( 6 ) . Cq ( ) . Text ( ) ) ;
int leechers = ParseUtil . CoerceInt ( cells . Elements . ElementAt ( 7 ) . Cq ( ) . Text ( ) ) ;
2016-01-19 13:08:00 +00:00
string pubDateStr = torrentData . Find ( "span[class^='elapsedDate']" ) . First ( ) . Attr ( "title" ) . Trim ( ) . Replace ( " at" , "" ) ;
DateTime publishDate = DateTime . ParseExact ( pubDateStr , "dddd, MMMM d, yyyy h:mmtt" , CultureInfo . InvariantCulture , DateTimeStyles . AssumeUniversal ) . ToLocalTime ( ) ;
long category = 0 ;
2018-08-29 10:26:48 +00:00
string cat = torrentData . Find ( "img[class^='Tcat']" ) . First ( ) . Parent ( ) . Attr ( "href" ) . Trim ( ) . Remove ( 0 , 5 ) ;
2016-01-19 13:08:00 +00:00
long . TryParse ( cat , out category ) ;
2015-12-09 08:45:44 +00:00
2016-01-19 13:08:00 +00:00
var release = new ReleaseInfo ( ) ;
release . Title = title ;
release . Guid = guid ;
release . Link = link ;
release . PublishDate = publishDate ;
release . Size = size ;
2018-08-29 10:26:48 +00:00
release . Grabs = grabs ;
2016-01-19 13:08:00 +00:00
release . Seeders = seeders ;
release . Peers = seeders + leechers ;
release . MinimumRatio = 1 ;
release . MinimumSeedTime = 172800 ;
release . Category = MapTrackerCatToNewznab ( category . ToString ( ) ) ;
2019-02-11 23:58:20 +00:00
release . Comments = comments ;
2015-07-19 02:19:09 +00:00
2017-02-24 18:16:57 +00:00
if ( torrentData . Find ( "span:contains(\"[Freeleech]\")" ) . Any ( ) )
release . DownloadVolumeFactor = 0 ;
else
2017-04-15 08:45:10 +00:00
release . DownloadVolumeFactor = 1 ;
2017-02-24 18:16:57 +00:00
release . UploadVolumeFactor = 1 ;
2015-07-19 02:19:09 +00:00
releases . Add ( release ) ;
}
}
catch ( Exception ex )
{
2015-07-27 00:03:51 +00:00
OnParseError ( response . Content , ex ) ;
2015-07-19 02:19:09 +00:00
}
2015-07-28 23:10:04 +00:00
return releases ;
2015-07-19 02:19:09 +00:00
}
}
2016-01-20 08:45:39 +00:00
}