2017-11-13 08:42:25 +00:00
using System ;
2017-10-29 06:50:47 +00:00
using System.Collections.Generic ;
using System.Collections.Specialized ;
using System.Linq ;
using System.Text ;
using System.Text.RegularExpressions ;
using System.Threading.Tasks ;
2020-02-29 19:43:12 +00:00
using AngleSharp.Html.Parser ;
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-04-15 08:45:10 +00:00
using Newtonsoft.Json.Linq ;
using NLog ;
2018-03-10 08:05:56 +00:00
namespace Jackett.Common.Indexers
2017-04-15 08:45:10 +00:00
{
2017-07-10 20:58:44 +00:00
public class TorrentSyndikat : BaseWebIndexer
2017-04-15 08:45:10 +00:00
{
2020-02-25 16:08:03 +00:00
private string SearchUrl = > SiteLink + "browse.php" ;
private string LoginUrl = > SiteLink + "eing2.php" ;
private string CaptchaUrl = > SiteLink + "simpleCaptcha.php?numImages=1" ;
2020-02-10 22:16:19 +00:00
private readonly TimeZoneInfo germanyTz ;
2017-04-15 08:45:10 +00:00
2017-10-29 06:50:47 +00:00
private new ConfigurationDataBasicLoginWithRSSAndDisplay configData
2017-04-15 08:45:10 +00:00
{
2020-02-25 16:08:03 +00:00
get = > ( ConfigurationDataBasicLoginWithRSSAndDisplay ) base . configData ;
set = > base . configData = value ;
2017-04-15 08:45:10 +00:00
}
2017-11-05 09:42:03 +00:00
public TorrentSyndikat ( IIndexerConfigurationService configService , WebClient w , Logger l , IProtectionService ps )
2017-04-15 08:45:10 +00:00
: base ( name : "Torrent-Syndikat" ,
description : "A German general tracker" ,
link : "https://torrent-syndikat.org/" ,
2020-04-03 22:37:42 +00:00
caps : new TorznabCapabilities
{
SupportsImdbMovieSearch = true
} ,
2017-07-10 20:58:44 +00:00
configService : configService ,
2017-04-15 08:45:10 +00:00
client : w ,
logger : l ,
p : ps ,
configData : new ConfigurationDataBasicLoginWithRSSAndDisplay ( ) )
{
2017-11-05 09:42:03 +00:00
Encoding = Encoding . UTF8 ;
2017-04-15 08:45:10 +00:00
Language = "de-de" ;
Type = "private" ;
2020-02-10 22:16:19 +00:00
configData . DisplayText . Value = "Only the results from the first search result page are shown, adjust your profile settings to show the maximum." ;
configData . DisplayText . Name = "Notice" ;
2017-04-15 08:45:10 +00:00
2018-03-25 15:14:27 +00:00
AddCategoryMapping ( 2 , TorznabCatType . PC , "Apps / Windows" ) ;
AddCategoryMapping ( 13 , TorznabCatType . PC , "Apps / Linux" ) ;
2018-09-05 16:00:05 +00:00
AddCategoryMapping ( 4 , TorznabCatType . PCMac , "Apps / MacOS" ) ;
2018-03-25 15:14:27 +00:00
AddCategoryMapping ( 6 , TorznabCatType . PC , "Apps / Misc" ) ;
2017-04-15 08:45:10 +00:00
2018-09-05 16:00:05 +00:00
AddCategoryMapping ( 50 , TorznabCatType . PCGames , "Spiele / Windows" ) ;
AddCategoryMapping ( 51 , TorznabCatType . PCGames , "Spiele / MacOS" ) ;
AddCategoryMapping ( 52 , TorznabCatType . PCGames , "Spiele / Linux" ) ;
AddCategoryMapping ( 8 , TorznabCatType . ConsoleOther , "Spiele / Playstation" ) ;
AddCategoryMapping ( 7 , TorznabCatType . ConsoleOther , "Spiele / Nintendo" ) ;
AddCategoryMapping ( 32 , TorznabCatType . ConsoleOther , "Spiele / XBOX" ) ;
2017-04-15 08:45:10 +00:00
2018-03-25 15:14:27 +00:00
AddCategoryMapping ( 42 , TorznabCatType . MoviesUHD , "Filme / 2160p" ) ;
AddCategoryMapping ( 9 , TorznabCatType . MoviesHD , "Filme / 1080p" ) ;
AddCategoryMapping ( 20 , TorznabCatType . MoviesHD , "Filme / 720p" ) ;
AddCategoryMapping ( 10 , TorznabCatType . MoviesSD , "Filme / SD" ) ;
2017-04-15 08:45:10 +00:00
2018-09-05 16:00:05 +00:00
AddCategoryMapping ( 43 , TorznabCatType . TVUHD , "Serien / 2160p" ) ;
AddCategoryMapping ( 53 , TorznabCatType . TVHD , "Serien / 1080p" ) ;
AddCategoryMapping ( 54 , TorznabCatType . TVHD , "Serien / 720p" ) ;
AddCategoryMapping ( 15 , TorznabCatType . TVSD , "Serien / SD" ) ;
AddCategoryMapping ( 30 , TorznabCatType . TVSport , "Serien / Sport" ) ;
2017-04-15 08:45:10 +00:00
2018-09-05 16:00:05 +00:00
AddCategoryMapping ( 44 , TorznabCatType . TVUHD , "Serienpacks / 2160p" ) ;
AddCategoryMapping ( 55 , TorznabCatType . TVHD , "Serienpacks / 1080p" ) ;
AddCategoryMapping ( 56 , TorznabCatType . TVHD , "Serienpacks / 720p" ) ;
AddCategoryMapping ( 27 , TorznabCatType . TVSD , "Serienpacks / SD" ) ;
AddCategoryMapping ( 24 , TorznabCatType . AudioLossless , "Audio / Musik / FLAC" ) ;
AddCategoryMapping ( 25 , TorznabCatType . AudioMP3 , "Audio / Musik / MP3" ) ;
2018-03-25 15:14:27 +00:00
AddCategoryMapping ( 35 , TorznabCatType . AudioOther , "Audio / Other" ) ;
AddCategoryMapping ( 18 , TorznabCatType . AudioAudiobook , "Audio / aBooks" ) ;
AddCategoryMapping ( 33 , TorznabCatType . AudioVideo , "Audio / Videos" ) ;
2017-04-15 08:45:10 +00:00
2018-03-25 15:14:27 +00:00
AddCategoryMapping ( 17 , TorznabCatType . Books , "Misc / eBooks" ) ;
AddCategoryMapping ( 5 , TorznabCatType . PCPhoneOther , "Misc / Mobile" ) ;
AddCategoryMapping ( 39 , TorznabCatType . Other , "Misc / Bildung" ) ;
2018-03-25 15:03:10 +00:00
2018-09-05 16:00:05 +00:00
AddCategoryMapping ( 36 , TorznabCatType . TVFOREIGN , "Englisch / Serien" ) ;
AddCategoryMapping ( 57 , TorznabCatType . TVFOREIGN , "Englisch / Serienpacks" ) ;
2018-03-25 15:14:27 +00:00
AddCategoryMapping ( 37 , TorznabCatType . MoviesForeign , "Englisch / Filme" ) ;
AddCategoryMapping ( 47 , TorznabCatType . Books , "Englisch / eBooks" ) ;
AddCategoryMapping ( 48 , TorznabCatType . Other , "Englisch / Bildung" ) ;
AddCategoryMapping ( 49 , TorznabCatType . TVSport , "Englisch / Sport" ) ;
2018-03-25 15:03:10 +00:00
2020-02-10 22:16:19 +00:00
var startTransition = TimeZoneInfo . TransitionTime . CreateFloatingDateRule ( new DateTime ( 1 , 1 , 1 , 3 , 0 , 0 ) , 3 , 5 , DayOfWeek . Sunday ) ;
var endTransition = TimeZoneInfo . TransitionTime . CreateFloatingDateRule ( new DateTime ( 1 , 1 , 1 , 4 , 0 , 0 ) , 10 , 5 , DayOfWeek . Sunday ) ;
var delta = new TimeSpan ( 1 , 0 , 0 ) ;
var adjustment = TimeZoneInfo . AdjustmentRule . CreateAdjustmentRule ( new DateTime ( 1999 , 10 , 1 ) , DateTime . MaxValue . Date , delta , startTransition , endTransition ) ;
2018-03-25 15:03:10 +00:00
TimeZoneInfo . AdjustmentRule [ ] adjustments = { adjustment } ;
germanyTz = TimeZoneInfo . CreateCustomTimeZone ( "W. Europe Standard Time" , new TimeSpan ( 1 , 0 , 0 ) , "(GMT+01:00) W. Europe Standard Time" , "W. Europe Standard Time" , "W. Europe DST Time" , adjustments ) ;
2020-02-09 02:35:16 +00:00
}
2017-04-15 08:45:10 +00:00
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 ) ;
2017-11-17 14:01:25 +00:00
CookieHeader = "" ;
2017-04-15 08:45:10 +00:00
var result1 = await RequestStringWithCookies ( CaptchaUrl ) ;
var json1 = JObject . Parse ( result1 . Content ) ;
var captchaSelection = json1 [ "images" ] [ 0 ] [ "hash" ] ;
var pairs = new Dictionary < string , string > {
{ "username" , configData . Username . Value } ,
{ "password" , configData . Password . Value } ,
{ "captchaSelection" , ( string ) captchaSelection } ,
{ "submitme" , "X" }
} ;
var result2 = await RequestLoginAndFollowRedirect ( LoginUrl , pairs , result1 . Cookies , true , null , null , true ) ;
2020-02-25 16:08:03 +00:00
await ConfigureIfOK ( result2 . Cookies , result2 . Content . Contains ( "/logout.php" ) ,
( ) = > throw new ExceptionWithConfigData ( result2 . Content , configData ) ) ;
2017-04-15 08:45:10 +00:00
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
{
2020-02-10 22:16:19 +00:00
var releases = new List < ReleaseInfo > ( ) ;
2020-03-21 23:06:22 +00:00
var queryCollection = new NameValueCollection
{
{ "incldead" , "1" } ,
{ "rel_type" , "0" } // Alle
} ;
2017-11-13 08:42:25 +00:00
2020-02-09 02:35:16 +00:00
if ( query . ImdbID ! = null )
2017-04-15 08:45:10 +00:00
{
2017-11-13 08:42:25 +00:00
queryCollection . Add ( "searchin" , "imdb" ) ;
queryCollection . Add ( "search" , query . ImdbID ) ;
2020-02-09 02:35:16 +00:00
}
else
{
2017-11-13 08:42:25 +00:00
queryCollection . Add ( "searchin" , "title" ) ;
2020-02-09 02:35:16 +00:00
2020-03-21 23:06:22 +00:00
if ( ! string . IsNullOrWhiteSpace ( query . GetQueryString ( ) ) )
2017-11-13 08:42:25 +00:00
{
// use AND+wildcard operator to avoid getting to many useless results
2020-03-21 23:06:22 +00:00
var searchStringArray = Regex . Split (
query . SanitizedSearchTerm , "[ _.-]+" ,
RegexOptions . Compiled ) . Select ( term = > $"+{term}" ) ;
// If only season search add * wildcard to get all episodes
var tvEpisode = query . GetEpisodeSearchString ( ) ;
if ( ! string . IsNullOrWhiteSpace ( tvEpisode ) )
{
2020-04-07 16:17:17 +00:00
if ( tvEpisode . StartsWith ( "S" ) & & ! tvEpisode . Contains ( "E" ) )
2020-03-21 23:06:22 +00:00
tvEpisode + = "*" ;
searchStringArray = searchStringArray . Append ( $"+{tvEpisode}" ) ;
}
queryCollection . Add ( "search" , string . Join ( " " , searchStringArray ) ) ;
2020-02-09 02:35:16 +00:00
}
2017-04-15 08:45:10 +00:00
2017-11-13 08:42:25 +00:00
}
2017-04-15 08:45:10 +00:00
foreach ( var cat in MapTorznabCapsToTrackers ( query ) )
queryCollection . Add ( "c" + cat , "1" ) ;
2020-03-21 23:06:22 +00:00
var searchUrl = SearchUrl + "?" + queryCollection . GetQueryString ( ) ;
2017-04-15 08:45:10 +00:00
var results = await RequestStringWithCookiesAndRetry ( searchUrl ) ;
2017-07-06 19:16:53 +00:00
if ( results . IsRedirect )
{
await ApplyConfiguration ( null ) ;
results = await RequestStringWithCookiesAndRetry ( searchUrl ) ;
}
2017-04-15 08:45:10 +00:00
try
{
2020-02-29 19:43:12 +00:00
var parser = new HtmlParser ( ) ;
var dom = parser . ParseDocument ( results . Content ) ;
var rows = dom . QuerySelectorAll ( "table.torrent_table > tbody > tr" ) ;
var globalFreeleech = dom . QuerySelector ( "legend:contains(\"Freeleech\")+ul > li > b:contains(\"Freeleech\")" ) ! = null ;
2017-04-15 08:45:10 +00:00
foreach ( var row in rows . Skip ( 1 ) )
{
2020-02-29 19:43:12 +00:00
var catStr = row . Children [ 0 ] . FirstElementChild . GetAttribute ( "href" ) . Split ( '=' ) [ 1 ] . Split ( '&' ) [ 0 ] ;
2017-04-15 08:45:10 +00:00
2020-02-29 19:43:12 +00:00
var qLink = row . Children [ 2 ] . FirstElementChild ;
var descCol = row . Children [ 1 ] ;
var torrentTag = descCol . QuerySelectorAll ( "span.torrent-tag" ) ;
2020-03-26 22:15:28 +00:00
//Empty list gives string.Empty in string.Join
var description = string . Join ( ", " , torrentTag . Select ( x = > x . InnerHtml ) ) ;
2020-03-03 20:35:13 +00:00
var qCommentLink = descCol . QuerySelector ( "a[href*=\"details.php\"]" ) ;
2020-03-26 22:15:28 +00:00
var comments = new Uri ( SiteLink + qCommentLink . GetAttribute ( "href" ) . Replace ( "&hit=1" , "" ) ) ;
2017-04-15 08:45:10 +00:00
2020-02-29 19:43:12 +00:00
var torrentDetails = descCol . QuerySelector ( ".torrent_details" ) ;
2020-03-03 20:35:13 +00:00
var rawDateStr = torrentDetails . ChildNodes [ 1 ] . TextContent ;
2020-03-26 22:15:28 +00:00
var dateStr = rawDateStr . Replace ( "von" , "" )
. Replace ( "Heute" , "Today" )
. Replace ( "Gestern" , "Yesterday" ) ;
2020-04-07 16:17:17 +00:00
var dateGerman = DateTimeUtil . FromUnknown ( dateStr ) ;
2020-02-10 22:16:19 +00:00
var pubDateUtc = TimeZoneInfo . ConvertTimeToUtc ( dateGerman , germanyTz ) ;
2020-03-26 22:15:28 +00:00
var longFromString = ParseUtil . GetLongFromString ( descCol . QuerySelector ( "a[href*=\"&searchin=imdb\"]" ) ? . GetAttribute ( "href" ) ) ;
2020-02-29 19:43:12 +00:00
var sizeFileCountRowChilds = row . Children [ 5 ] . Children ;
2020-03-26 22:15:28 +00:00
var seeders = ParseUtil . CoerceInt ( row . Children [ 7 ] . TextContent ) ;
var link = new Uri ( SiteLink + qLink . GetAttribute ( "href" ) ) ;
var files = ParseUtil . CoerceInt ( sizeFileCountRowChilds [ 2 ] . TextContent ) ;
var leechers = ParseUtil . CoerceInt ( row . Children [ 8 ] . TextContent ) ;
var grabs = ParseUtil . CoerceInt ( row . QuerySelector ( "td:nth-child(7)" ) . TextContent ) ;
var downloadVolumeFactor = globalFreeleech | | row . QuerySelector ( "span.torrent-tag-free" ) ! = null
? 0 : 1 ;
var size = ReleaseInfo . GetBytes ( sizeFileCountRowChilds [ 0 ] . TextContent ) ;
var release = new ReleaseInfo
{
MinimumRatio = 1 ,
MinimumSeedTime = 345600 , //8 days
Category = MapTrackerCatToNewznab ( catStr ) ,
Link = link ,
Description = description ,
Title = qCommentLink . GetAttribute ( "title" ) ,
Comments = comments ,
Guid = comments ,
PublishDate = pubDateUtc . ToLocalTime ( ) ,
Imdb = longFromString ,
Size = size ,
Files = files ,
Seeders = seeders ,
Peers = leechers + seeders ,
Grabs = grabs ,
DownloadVolumeFactor = downloadVolumeFactor ,
UploadVolumeFactor = 1
} ;
2017-04-15 08:45:10 +00:00
releases . Add ( release ) ;
}
}
catch ( Exception ex )
{
OnParseError ( results . Content , ex ) ;
}
return releases ;
}
}
}