2020-02-09 02:35:16 +00:00
using System ;
2015-04-16 01:16:16 +00:00
using System.Collections.Generic ;
2015-07-29 19:30:28 +00:00
using System.Collections.Specialized ;
2020-05-03 23:35:52 +00:00
using System.Diagnostics.CodeAnalysis ;
2015-04-16 01:16:16 +00:00
using System.Linq ;
2023-02-10 13:37:08 +00:00
using System.Text.RegularExpressions ;
2015-04-16 01:16:16 +00:00
using System.Threading.Tasks ;
2020-02-28 22:33:21 +00:00
using AngleSharp.Html.Parser ;
2024-02-06 11:39:19 +00:00
using Jackett.Common.Extensions ;
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 ;
2020-06-11 15:09:27 +00:00
using Jackett.Common.Utils.Clients ;
2017-10-29 06:21:18 +00:00
using Newtonsoft.Json.Linq ;
using NLog ;
2021-01-31 11:46:23 +00:00
using static Jackett . Common . Models . IndexerConfig . ConfigurationData ;
2015-04-16 01:16:16 +00:00
2018-03-10 08:05:56 +00:00
namespace Jackett.Common.Indexers
2015-04-16 01:16:16 +00:00
{
2020-05-03 23:35:52 +00:00
[ExcludeFromCodeCoverage]
2023-03-09 14:06:12 +00:00
public class IPTorrents : IndexerBase
2015-05-04 04:12:14 +00:00
{
2023-03-09 14:06:12 +00:00
public override string Id = > "iptorrents" ;
public override string Name = > "IPTorrents" ;
public override string Description = > "Always a step ahead." ;
public override string SiteLink { get ; protected set ; } = "https://iptorrents.com/" ;
public override string [ ] AlternativeSiteLinks = > new [ ]
{
2017-08-31 09:13:09 +00:00
"https://iptorrents.com/" ,
2019-02-03 05:53:09 +00:00
"https://www.iptorrents.com/" ,
2021-01-12 11:13:00 +00:00
"https://iptorrents.me/" ,
2017-08-31 09:13:09 +00:00
"https://nemo.iptorrents.com/" ,
2024-02-14 18:24:26 +00:00
"https://ip.findnemo.net/" ,
"https://ip.venom.global/" ,
"https://ip.getcrazy.me/" ,
"https://ip.workisboring.net/" ,
2020-02-08 01:47:17 +00:00
"https://ipt.cool/" ,
2024-02-14 18:24:26 +00:00
"https://ipt.lol/" ,
2023-07-27 09:20:41 +00:00
"https://ipt.world/" ,
"https://ipt.octopus.town/"
2020-05-15 21:06:58 +00:00
} ;
2023-03-09 14:06:12 +00:00
public override string [ ] LegacySiteLinks = > new [ ]
{
2020-05-15 21:06:58 +00:00
"https://ipt-update.com/" ,
"http://ipt.read-books.org/" ,
"http://alien.eating-organic.net/" ,
"http://kong.net-freaks.com/" ,
"http://ghost.cable-modem.org/" ,
"http://logan.unusualperson.com/" ,
2020-09-12 22:52:50 +00:00
"https://ipt.rocks/" ,
2021-01-12 11:13:00 +00:00
"http://baywatch.workisboring.com/" ,
2024-02-14 18:24:26 +00:00
"https://iptorrents.eu/" ,
"https://ipt.getcrazy.me/" ,
"https://ipt.findnemo.net/" ,
"https://ipt.beelyrics.net/" ,
"https://ipt.venom.global/" ,
"https://ipt.workisboring.net/"
2017-08-31 09:13:09 +00:00
} ;
2023-03-09 14:06:12 +00:00
public override string Language = > "en-US" ;
public override string Type = > "private" ;
public override bool SupportsPagination = > true ;
2023-03-10 11:20:29 +00:00
public override TorznabCapabilities TorznabCaps = > SetCapabilities ( ) ;
2023-03-09 14:06:12 +00:00
private string SearchUrl = > SiteLink + "t" ;
2015-07-22 22:00:52 +00:00
2022-02-11 21:59:17 +00:00
private new ConfigurationDataCookieUA configData = > ( ConfigurationDataCookieUA ) base . configData ;
2015-08-03 21:38:45 +00:00
2020-12-11 22:14:21 +00:00
public IPTorrents ( IIndexerConfigurationService configService , WebClient wc , Logger l , IProtectionService ps ,
ICacheService cs )
2023-03-10 11:20:29 +00:00
: base ( configService : configService ,
2020-04-04 20:34:19 +00:00
client : wc ,
logger : l ,
p : ps ,
2020-12-11 22:14:21 +00:00
cacheService : cs ,
2024-04-09 00:50:07 +00:00
configData : new ConfigurationDataCookieUA ( "In the website Settings:<ul><li>change the <b>Torrents per page</b> option to <b>100</b></li><li><b>Tick</b> the <b>Torrents - Show files count</b> checkbox</li><li>Set the <b>torrents category column</b> to <b>Icons</b></li></ul>Otherwise the indexer may not return results." ) )
2015-05-04 04:12:14 +00:00
{
2023-02-10 13:37:08 +00:00
var sort = new SingleSelectConfigurationItem ( "Sort requested from site" , new Dictionary < string , string >
2022-01-19 00:16:19 +00:00
{
{ "time" , "created" } ,
{ "size" , "size" } ,
{ "seeders" , "seeders" } ,
{ "name" , "title" }
} )
{ Value = "time" } ;
configData . AddDynamic ( "sort" , sort ) ;
2021-03-16 23:29:26 +00:00
configData . AddDynamic ( "freeleech" , new BoolConfigurationItem ( "Search freeleech only" ) { Value = false } ) ;
2024-02-27 20:13:36 +00:00
configData . AddDynamic ( "Account Inactivity" , new DisplayInfoConfigurationItem ( "Account Inactivity" , "All members are required to log into their account at least every 89 days or you will be deleted without warning." ) ) ;
2023-03-10 11:20:29 +00:00
}
2021-01-31 11:46:23 +00:00
2023-03-10 11:20:29 +00:00
private TorznabCapabilities SetCapabilities ( )
{
var caps = new TorznabCapabilities
{
TvSearchParams = new List < TvSearchParam >
{
TvSearchParam . Q , TvSearchParam . Season , TvSearchParam . Ep , TvSearchParam . ImdbId , TvSearchParam . Genre
} ,
MovieSearchParams = new List < MovieSearchParam >
{
MovieSearchParam . Q , MovieSearchParam . ImdbId , MovieSearchParam . Genre
} ,
MusicSearchParams = new List < MusicSearchParam >
{
MusicSearchParam . Q
} ,
BookSearchParams = new List < BookSearchParam >
{
BookSearchParam . Q
} ,
TvSearchImdbAvailable = true
} ;
caps . Categories . AddCategoryMapping ( 72 , TorznabCatType . Movies , "Movies" ) ;
caps . Categories . AddCategoryMapping ( 87 , TorznabCatType . Movies3D , "Movie/3D" ) ;
caps . Categories . AddCategoryMapping ( 77 , TorznabCatType . MoviesSD , "Movie/480p" ) ;
caps . Categories . AddCategoryMapping ( 101 , TorznabCatType . MoviesUHD , "Movie/4K" ) ;
caps . Categories . AddCategoryMapping ( 89 , TorznabCatType . MoviesBluRay , "Movie/BD-R" ) ;
caps . Categories . AddCategoryMapping ( 90 , TorznabCatType . MoviesHD , "Movie/BD-Rip" ) ;
caps . Categories . AddCategoryMapping ( 96 , TorznabCatType . MoviesSD , "Movie/Cam" ) ;
caps . Categories . AddCategoryMapping ( 6 , TorznabCatType . MoviesDVD , "Movie/DVD-R" ) ;
caps . Categories . AddCategoryMapping ( 48 , TorznabCatType . MoviesHD , "Movie/HD/Bluray" ) ;
caps . Categories . AddCategoryMapping ( 54 , TorznabCatType . Movies , "Movie/Kids" ) ;
caps . Categories . AddCategoryMapping ( 62 , TorznabCatType . MoviesSD , "Movie/MP4" ) ;
caps . Categories . AddCategoryMapping ( 38 , TorznabCatType . MoviesForeign , "Movie/Non-English" ) ;
caps . Categories . AddCategoryMapping ( 68 , TorznabCatType . Movies , "Movie/Packs" ) ;
caps . Categories . AddCategoryMapping ( 20 , TorznabCatType . MoviesWEBDL , "Movie/Web-DL" ) ;
caps . Categories . AddCategoryMapping ( 100 , TorznabCatType . MoviesHD , "Movie/x265" ) ;
caps . Categories . AddCategoryMapping ( 7 , TorznabCatType . MoviesSD , "Movie/Xvid" ) ;
caps . Categories . AddCategoryMapping ( 73 , TorznabCatType . TV , "TV" ) ;
caps . Categories . AddCategoryMapping ( 26 , TorznabCatType . TVDocumentary , "TV/Documentaries" ) ;
caps . Categories . AddCategoryMapping ( 55 , TorznabCatType . TVSport , "Sports" ) ;
caps . Categories . AddCategoryMapping ( 78 , TorznabCatType . TVSD , "TV/480p" ) ;
caps . Categories . AddCategoryMapping ( 23 , TorznabCatType . TVHD , "TV/BD" ) ;
caps . Categories . AddCategoryMapping ( 24 , TorznabCatType . TVSD , "TV/DVD-R" ) ;
caps . Categories . AddCategoryMapping ( 25 , TorznabCatType . TVSD , "TV/DVD-Rip" ) ;
caps . Categories . AddCategoryMapping ( 66 , TorznabCatType . TVSD , "TV/Mobile" ) ;
caps . Categories . AddCategoryMapping ( 82 , TorznabCatType . TVForeign , "TV/Non-English" ) ;
caps . Categories . AddCategoryMapping ( 65 , TorznabCatType . TV , "TV/Packs" ) ;
caps . Categories . AddCategoryMapping ( 83 , TorznabCatType . TVForeign , "TV/Packs/Non-English" ) ;
caps . Categories . AddCategoryMapping ( 79 , TorznabCatType . TVSD , "TV/SD/x264" ) ;
caps . Categories . AddCategoryMapping ( 22 , TorznabCatType . TVWEBDL , "TV/Web-DL" ) ;
caps . Categories . AddCategoryMapping ( 5 , TorznabCatType . TVHD , "TV/x264" ) ;
caps . Categories . AddCategoryMapping ( 99 , TorznabCatType . TVHD , "TV/x265" ) ;
caps . Categories . AddCategoryMapping ( 4 , TorznabCatType . TVSD , "TV/Xvid" ) ;
caps . Categories . AddCategoryMapping ( 74 , TorznabCatType . Console , "Games" ) ;
caps . Categories . AddCategoryMapping ( 2 , TorznabCatType . ConsoleOther , "Games/Mixed" ) ;
caps . Categories . AddCategoryMapping ( 47 , TorznabCatType . ConsoleOther , "Games/Nintendo" ) ;
caps . Categories . AddCategoryMapping ( 43 , TorznabCatType . PCGames , "Games/PC-ISO" ) ;
caps . Categories . AddCategoryMapping ( 45 , TorznabCatType . PCGames , "Games/PC-Rip" ) ;
caps . Categories . AddCategoryMapping ( 71 , TorznabCatType . ConsolePS4 , "Games/Playstation" ) ;
caps . Categories . AddCategoryMapping ( 50 , TorznabCatType . ConsoleWii , "Games/Wii" ) ;
caps . Categories . AddCategoryMapping ( 44 , TorznabCatType . ConsoleXBox , "Games/Xbox" ) ;
caps . Categories . AddCategoryMapping ( 75 , TorznabCatType . Audio , "Music" ) ;
caps . Categories . AddCategoryMapping ( 3 , TorznabCatType . AudioMP3 , "Music/Audio" ) ;
caps . Categories . AddCategoryMapping ( 80 , TorznabCatType . AudioLossless , "Music/Flac" ) ;
caps . Categories . AddCategoryMapping ( 93 , TorznabCatType . Audio , "Music/Packs" ) ;
caps . Categories . AddCategoryMapping ( 37 , TorznabCatType . AudioVideo , "Music/Video" ) ;
caps . Categories . AddCategoryMapping ( 21 , TorznabCatType . AudioOther , "Podcast" ) ;
caps . Categories . AddCategoryMapping ( 76 , TorznabCatType . Other , "Miscellaneous" ) ;
caps . Categories . AddCategoryMapping ( 60 , TorznabCatType . TVAnime , "Anime" ) ;
caps . Categories . AddCategoryMapping ( 1 , TorznabCatType . PC0day , "Appz" ) ;
caps . Categories . AddCategoryMapping ( 86 , TorznabCatType . PC0day , "Appz/Non-English" ) ;
caps . Categories . AddCategoryMapping ( 64 , TorznabCatType . AudioAudiobook , "AudioBook" ) ;
caps . Categories . AddCategoryMapping ( 35 , TorznabCatType . Books , "Books" ) ;
caps . Categories . AddCategoryMapping ( 102 , TorznabCatType . Books , "Books/Non-English" ) ;
caps . Categories . AddCategoryMapping ( 94 , TorznabCatType . BooksComics , "Comics" ) ;
caps . Categories . AddCategoryMapping ( 95 , TorznabCatType . BooksOther , "Educational" ) ;
caps . Categories . AddCategoryMapping ( 98 , TorznabCatType . Other , "Fonts" ) ;
caps . Categories . AddCategoryMapping ( 69 , TorznabCatType . PCMac , "Mac" ) ;
caps . Categories . AddCategoryMapping ( 92 , TorznabCatType . BooksMags , "Magazines / Newspapers" ) ;
caps . Categories . AddCategoryMapping ( 58 , TorznabCatType . PCMobileOther , "Mobile" ) ;
caps . Categories . AddCategoryMapping ( 36 , TorznabCatType . Other , "Pics/Wallpapers" ) ;
caps . Categories . AddCategoryMapping ( 88 , TorznabCatType . XXX , "XXX" ) ;
caps . Categories . AddCategoryMapping ( 85 , TorznabCatType . XXXOther , "XXX/Magazines" ) ;
caps . Categories . AddCategoryMapping ( 8 , TorznabCatType . XXX , "XXX/Movie" ) ;
caps . Categories . AddCategoryMapping ( 81 , TorznabCatType . XXX , "XXX/Movie/0Day" ) ;
caps . Categories . AddCategoryMapping ( 91 , TorznabCatType . XXXPack , "XXX/Packs" ) ;
caps . Categories . AddCategoryMapping ( 84 , TorznabCatType . XXXImageSet , "XXX/Pics/Wallpapers" ) ;
return caps ;
2015-05-04 04:12:14 +00:00
}
2015-04-23 06:44:21 +00:00
2023-09-03 04:11:21 +00:00
public override void LoadValuesFromJson ( JToken jsonConfig , bool useProtectionService = false )
{
base . LoadValuesFromJson ( jsonConfig , useProtectionService ) ;
2024-03-03 00:31:31 +00:00
webclient ? . AddTrustedCertificate ( new Uri ( SiteLink ) . Host , "1C54573353A97C17DD2344E9E7094848046A8CDA" ) ; // for *.octopus.town expired 01/Mar/24
2023-09-03 04:11:21 +00:00
}
2017-06-28 05:31:38 +00:00
public override async Task < IndexerConfigurationStatus > ApplyConfiguration ( JToken configJson )
2015-05-04 04:12:14 +00:00
{
2017-01-02 20:39:28 +00:00
LoadValuesFromJson ( configJson ) ;
2016-11-05 18:25:38 +00:00
2020-02-22 19:34:14 +00:00
CookieHeader = configData . Cookie . Value ;
2022-02-11 21:59:17 +00:00
2020-02-22 19:34:14 +00:00
try
2016-11-05 18:25:38 +00:00
{
2020-02-22 19:34:14 +00:00
var results = await PerformQuery ( new TorznabQuery ( ) ) ;
if ( ! results . Any ( ) )
2023-12-11 13:51:44 +00:00
{
2020-04-26 18:18:40 +00:00
throw new Exception ( "Found 0 results in the tracker" ) ;
2023-12-11 13:51:44 +00:00
}
2016-11-05 18:25:38 +00:00
2020-02-22 19:34:14 +00:00
IsConfigured = true ;
SaveConfig ( ) ;
return IndexerConfigurationStatus . Completed ;
}
catch ( Exception e )
2015-07-22 22:00:52 +00:00
{
2020-02-22 19:34:14 +00:00
IsConfigured = false ;
2022-02-11 21:59:17 +00:00
throw new Exception ( "Your cookie did not work, make sure the user agent matches your computer: " + e . Message ) ;
2020-02-22 19:34:14 +00:00
}
2015-05-04 04:12:14 +00:00
}
2017-07-03 05:15:47 +00:00
protected override async Task < IEnumerable < ReleaseInfo > > PerformQuery ( TorznabQuery query )
2015-05-04 04:12:14 +00:00
{
2015-07-19 17:18:54 +00:00
var releases = new List < ReleaseInfo > ( ) ;
2015-07-29 19:30:28 +00:00
2023-02-10 13:37:08 +00:00
var validTagList = new List < string >
{
2022-08-09 01:55:29 +00:00
"action" ,
"adventure" ,
"animation" ,
"biography" ,
"comedy" ,
"crime" ,
"documentary" ,
"drama" ,
"family" ,
"fantasy" ,
"game-show" ,
"history" ,
"horror" ,
"music" ,
"musical" ,
"mystery" ,
"news" ,
"reality-tv" ,
"romance" ,
"sci-fi" ,
"sitcom" ,
"sport" ,
"talk-show" ,
"thriller" ,
"war" ,
"western"
} ;
2023-02-10 13:37:08 +00:00
/ * notes :
2022-08-09 01:55:29 +00:00
* IPTorrents can search for genre ( tags ) using the default title & tags search
2023-02-10 13:37:08 +00:00
* qf =
2022-08-09 01:55:29 +00:00
* "" = Title and Tags
* ti = Title
* ta = Tags
* all = Title , Tags & Description
* adv = Advanced
2023-02-10 13:37:08 +00:00
*
2022-08-09 01:55:29 +00:00
* But only movies and tv have tags .
* /
2023-02-10 13:37:08 +00:00
var headers = new Dictionary < string , string > ( ) ;
if ( ! string . IsNullOrEmpty ( configData . UserAgent . Value ) )
2023-12-11 13:51:44 +00:00
{
2023-02-10 13:37:08 +00:00
headers . Add ( "User-Agent" , configData . UserAgent . Value ) ;
2023-12-11 13:51:44 +00:00
}
2023-02-10 13:37:08 +00:00
2020-04-04 20:34:19 +00:00
var qc = new NameValueCollection ( ) ;
2015-07-29 19:30:28 +00:00
2023-02-10 13:37:08 +00:00
foreach ( var cat in MapTorznabCapsToTrackers ( query ) )
2023-12-11 13:51:44 +00:00
{
2023-02-10 13:37:08 +00:00
qc . Set ( cat , string . Empty ) ;
2023-12-11 13:51:44 +00:00
}
2022-02-11 21:59:17 +00:00
2023-02-10 13:37:08 +00:00
if ( ( ( BoolConfigurationItem ) configData . GetDynamic ( "freeleech" ) ) . Value )
2023-12-11 13:51:44 +00:00
{
2023-02-10 13:37:08 +00:00
qc . Set ( "free" , "on" ) ;
2023-12-11 13:51:44 +00:00
}
2022-02-11 21:59:17 +00:00
2023-02-10 13:37:08 +00:00
var searchQuery = new List < string > ( ) ;
2022-02-11 21:59:17 +00:00
2023-02-10 13:37:08 +00:00
// IPT uses sphinx, which supports boolean operators and grouping
2020-04-04 20:34:19 +00:00
if ( query . IsImdbQuery )
2023-12-11 13:51:44 +00:00
{
2023-02-10 13:37:08 +00:00
searchQuery . Add ( $"+({query.ImdbID})" ) ;
2023-12-11 13:51:44 +00:00
}
2023-02-10 13:37:08 +00:00
else if ( query . IsGenreQuery )
2023-12-11 13:51:44 +00:00
{
2023-02-10 13:37:08 +00:00
searchQuery . Add ( $"+({query.Genre})" ) ;
2023-12-11 13:51:44 +00:00
}
2023-02-10 13:37:08 +00:00
2024-02-06 11:39:19 +00:00
var searchTerm = query . GetQueryString ( ) ;
if ( searchTerm . IsNotNullOrWhiteSpace ( ) )
2023-12-11 13:51:44 +00:00
{
2024-02-06 11:39:19 +00:00
if ( query . GetEpisodeSearchString ( ) . IsNotNullOrWhiteSpace ( ) & & query . Season > 0 & & query . Episode . IsNullOrWhiteSpace ( ) )
{
searchTerm + = "*" ;
}
searchQuery . Add ( $"+({searchTerm})" ) ;
2023-12-11 13:51:44 +00:00
}
2015-07-29 19:30:28 +00:00
2023-02-10 13:37:08 +00:00
if ( searchQuery . Any ( ) )
2023-12-11 13:51:44 +00:00
{
2023-02-10 13:37:08 +00:00
qc . Set ( "q" , $"{string.Join(" ", searchQuery)}" ) ;
2023-12-11 13:51:44 +00:00
}
2015-08-03 21:38:45 +00:00
2023-02-10 13:37:08 +00:00
qc . Set ( "o" , ( ( SingleSelectConfigurationItem ) configData . GetDynamic ( "sort" ) ) . Value ) ;
2022-01-19 00:16:19 +00:00
2023-03-05 12:30:40 +00:00
if ( query . Limit > 0 & & query . Offset > 0 )
{
var page = query . Offset / query . Limit + 1 ;
qc . Add ( "p" , page . ToString ( ) ) ;
}
2020-04-04 20:34:19 +00:00
var searchUrl = SearchUrl + "?" + qc . GetQueryString ( ) ;
2022-02-11 21:59:17 +00:00
var response = await RequestWithCookiesAndRetryAsync ( searchUrl , referer : SearchUrl , headers : headers ) ;
2020-06-09 17:36:57 +00:00
var results = response . ContentString ;
2018-12-02 09:33:18 +00:00
2020-02-08 06:11:11 +00:00
if ( results = = null | | ! results . Contains ( "/lout.php" ) )
2023-12-11 13:51:44 +00:00
{
2020-02-08 06:11:11 +00:00
throw new Exception ( "The user is not logged in. It is possible that the cookie has expired or you made a mistake when copying it. Please check the settings." ) ;
2023-12-11 13:51:44 +00:00
}
2020-02-08 06:11:11 +00:00
2018-12-15 09:23:41 +00:00
if ( string . IsNullOrWhiteSpace ( query . ImdbID ) & & string . IsNullOrWhiteSpace ( query . SearchTerm ) & & results . Contains ( "No Torrents Found!" ) )
2023-12-11 13:51:44 +00:00
{
2018-12-02 09:33:18 +00:00
throw new Exception ( "Got No Torrents Found! Make sure your IPTorrents profile config contain proper default category settings." ) ;
2023-12-11 13:51:44 +00:00
}
2018-12-02 09:33:18 +00:00
2023-02-10 13:37:08 +00:00
char [ ] delimiters = { ',' , ' ' , '/' , ')' , '(' , '.' , ';' , '[' , ']' , '"' , '|' , ':' } ;
2015-07-18 20:35:02 +00:00
try
{
2020-04-04 20:34:19 +00:00
var parser = new HtmlParser ( ) ;
2023-10-05 01:06:23 +00:00
using var doc = parser . ParseDocument ( results ) ;
2015-05-04 04:12:14 +00:00
2023-12-11 13:51:44 +00:00
var headerColumns = doc . QuerySelectorAll ( "table[id=\"torrents\"] > thead > tr > th" ) . Select ( x = > x . TextContent . Trim ( ) ) . ToList ( ) ;
var sizeIndex = FindColumnIndexOrDefault ( headerColumns , "Sort by size" , 5 ) ;
var filesIndex = FindColumnIndexOrDefault ( headerColumns , "Sort by files" ) ;
2023-02-10 13:37:08 +00:00
var rows = doc . QuerySelectorAll ( "table[id=\"torrents\"] > tbody > tr" ) ;
2020-11-01 12:41:52 +00:00
foreach ( var row in rows )
2015-05-04 04:12:14 +00:00
{
2020-11-01 06:11:52 +00:00
var qTitleLink = row . QuerySelector ( "a.hv" ) ;
2020-04-07 14:50:04 +00:00
if ( qTitleLink = = null ) // no results
2023-12-11 13:51:44 +00:00
{
2020-04-07 14:50:04 +00:00
continue ;
2023-12-11 13:51:44 +00:00
}
2020-04-07 14:50:04 +00:00
2023-02-10 13:37:08 +00:00
var title = CleanTitle ( qTitleLink . TextContent ) ;
2023-12-13 19:34:26 +00:00
if ( ! query . IsImdbQuery & & ! query . IsGenreQuery & & ! query . MatchQueryStringAND ( title ) )
{
continue ;
}
2020-11-08 02:11:27 +00:00
var details = new Uri ( SiteLink + qTitleLink . GetAttribute ( "href" ) . TrimStart ( '/' ) ) ;
2015-07-18 20:35:02 +00:00
2020-02-28 22:33:21 +00:00
var qLink = row . QuerySelector ( "a[href^=\"/download.php/\"]" ) ;
2020-04-04 20:34:19 +00:00
var link = new Uri ( SiteLink + qLink . GetAttribute ( "href" ) . TrimStart ( '/' ) ) ;
2015-07-18 20:35:02 +00:00
2020-11-01 06:11:52 +00:00
var descrSplit = row . QuerySelector ( "div.sub" ) . TextContent . Split ( '|' ) ;
2021-05-16 18:13:54 +00:00
var dateSplit = descrSplit . Last ( ) . Split ( new [ ] { " by " } , StringSplitOptions . None ) ;
2020-11-01 12:41:52 +00:00
var publishDate = DateTimeUtil . FromTimeAgo ( dateSplit . First ( ) ) ;
2020-04-04 20:34:19 +00:00
var description = descrSplit . Length > 1 ? "Tags: " + descrSplit . First ( ) . Trim ( ) : "" ;
2020-11-01 12:41:52 +00:00
description + = dateSplit . Length > 1 ? " Uploaded by: " + dateSplit . Last ( ) . Trim ( ) : "" ;
2023-02-10 13:37:08 +00:00
var releaseGenres = validTagList . Intersect ( description . ToLower ( ) . Split ( delimiters , StringSplitOptions . RemoveEmptyEntries ) ) . ToList ( ) ;
2022-08-09 01:55:29 +00:00
2023-12-11 14:05:44 +00:00
// Torrents - Category column == Text or Code
// release.Category = MapTrackerCatDescToNewznab(row.Cq().Find("td:eq(0)").Text()); // Works for "Text" but only contains the parent category
2024-04-09 01:47:31 +00:00
var catIcon = row . QuerySelector ( "td:nth-of-type(1) a[href^=\"?\"]" ) ;
2020-04-04 20:34:19 +00:00
if ( catIcon = = null )
2023-12-11 13:51:44 +00:00
{
2020-04-04 20:34:19 +00:00
throw new Exception ( "Please, change the 'Torrents - Category column' option to 'Icons' in the website Settings. Wait a minute (cache) and then try again." ) ;
2023-12-11 13:51:44 +00:00
}
2020-04-04 20:34:19 +00:00
// Torrents - Category column == Icons
2024-04-09 01:47:31 +00:00
var cat = MapTrackerCatToNewznab ( catIcon . GetAttribute ( "href" ) ? . Substring ( 1 ) ) ;
2020-04-04 20:34:19 +00:00
2023-12-11 13:51:44 +00:00
var size = ParseUtil . GetBytes ( row . Children [ sizeIndex ] . TextContent ) ;
2020-11-01 16:42:04 +00:00
int? files = null ;
2023-12-11 13:51:44 +00:00
if ( filesIndex ! = - 1 )
2020-11-01 16:42:04 +00:00
{
2023-12-11 13:51:44 +00:00
// files column is enabled in the site settings
files = ParseUtil . CoerceInt ( row . Children [ filesIndex ] . TextContent . Replace ( "Go to files" , "" ) ) ;
2020-11-01 16:42:04 +00:00
}
2023-12-11 13:51:44 +00:00
var colIndex = row . Children . Length = = 10 ? 7 : 6 ;
var grabsIndex = FindColumnIndexOrDefault ( headerColumns , "Sort by snatches" , colIndex + + ) ;
var seedersIndex = FindColumnIndexOrDefault ( headerColumns , "Sort by seeders" , colIndex + + ) ;
var leechersIndex = FindColumnIndexOrDefault ( headerColumns , "Sort by leechers" , colIndex ) ;
var grabs = ParseUtil . CoerceInt ( row . Children [ grabsIndex ] . TextContent ) ;
var seeders = ParseUtil . CoerceInt ( row . Children [ seedersIndex ] . TextContent ) ;
var leechers = ParseUtil . CoerceInt ( row . Children [ leechersIndex ] . TextContent ) ;
2020-04-04 20:34:19 +00:00
var release = new ReleaseInfo
{
2020-11-08 02:11:27 +00:00
Guid = details ,
2020-04-04 20:34:19 +00:00
Link = link ,
2023-12-11 13:51:44 +00:00
Details = details ,
Title = title ,
2020-04-04 20:34:19 +00:00
Category = cat ,
Description = description ,
2023-02-10 13:37:08 +00:00
Genres = releaseGenres ,
2020-04-04 20:34:19 +00:00
Size = size ,
2020-11-01 16:42:04 +00:00
Files = files ,
2020-04-04 20:34:19 +00:00
Grabs = grabs ,
Seeders = seeders ,
Peers = seeders + leechers ,
2023-12-11 13:51:44 +00:00
PublishDate = publishDate ,
DownloadVolumeFactor = row . QuerySelector ( "span.free" ) ! = null ? 0 : 1 ,
2020-04-04 20:34:19 +00:00
UploadVolumeFactor = 1 ,
MinimumRatio = 1 ,
MinimumSeedTime = 1209600 // 336 hours
} ;
2016-10-27 07:35:31 +00:00
2015-07-18 20:35:02 +00:00
releases . Add ( release ) ;
2015-05-04 04:12:14 +00:00
}
2015-07-18 20:35:02 +00:00
}
catch ( Exception ex )
{
2015-07-19 17:18:54 +00:00
OnParseError ( results , ex ) ;
2015-05-04 04:12:14 +00:00
}
2015-07-28 23:10:04 +00:00
return releases ;
2015-05-04 04:12:14 +00:00
}
2023-02-10 13:37:08 +00:00
2023-12-11 13:51:44 +00:00
private static int FindColumnIndexOrDefault ( List < string > columns , string name , int defaultIndex = - 1 )
{
var index = columns . FindIndex ( x = > x . Equals ( name , StringComparison . Ordinal ) ) ;
return index ! = - 1 ? index : defaultIndex ;
}
2023-02-10 13:37:08 +00:00
private static string CleanTitle ( string title )
{
// drop invalid chars that seems to have cropped up in some titles. #6582
title = Regex . Replace ( title , @"[\u0000-\u0008\u000A-\u001F\u0100-\uFFFF]" , string . Empty , RegexOptions . Compiled ) ;
title = Regex . Replace ( title , @"[\(\[\{]REQ(UEST(ED)?)?[\)\]\}]" , string . Empty , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
return title . Trim ( ' ' , '-' , ':' ) ;
}
2015-05-04 04:12:14 +00:00
}
2015-04-16 01:16:16 +00:00
}