|
|
@@ -16,7 +16,7 @@ my $TV_DIR = `~/bin/video/mediaPath` . '/TV';
|
|
|
|
|
|
# Search parameters
|
|
|
my $PROTOCOL = 'http';
|
|
|
-my %ENABLE_SOURCE = ('TPB' => 1, 'ISO' => 1);
|
|
|
+my %ENABLE_SOURCE = ('TPB' => 0, 'ISO' => 1, 'KICK' => 1);
|
|
|
|
|
|
# Selection parameters
|
|
|
my $MIN_COUNT = 10;
|
|
|
@@ -30,7 +30,7 @@ my $SEED_RATIO_COUNT = 10;
|
|
|
# App config
|
|
|
my $DELAY = 4;
|
|
|
my $TIMEOUT = 15;
|
|
|
-my $UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9) AppleWebKit/537.71 (KHTML, like Gecko) Version/7.0 Safari/537.71';
|
|
|
+my $UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A';
|
|
|
|
|
|
# Includes
|
|
|
use JSON;
|
|
|
@@ -147,6 +147,39 @@ if ($ENABLE_SOURCE{'ISO'}) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+# Kickass
|
|
|
+if ($ENABLE_SOURCE{'KICK'}) {
|
|
|
+
|
|
|
+ # Available Kickass proxies, in order of preference
|
|
|
+ my @KICKs = ('kickass.so/usearch/');
|
|
|
+
|
|
|
+ # Automatically select a proxy that returns the non-US page
|
|
|
+ my $host = '';
|
|
|
+ my $search_url = '';
|
|
|
+ foreach my $url (@KICKs) {
|
|
|
+ ($host) = $url =~ /^([^\/]+)/;
|
|
|
+ $fetch->url($PROTOCOL . '://' . $host);
|
|
|
+ if ($fetch->fetch('nocheck' => 1) == 200 && $fetch->content() =~ /torrent name\<\/th\>/i) {
|
|
|
+ $search_url = $url;
|
|
|
+ last;
|
|
|
+ } elsif ($DEBUG) {
|
|
|
+ print STDERR 'Kickass proxy not available: ' . $host . "\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ # Only add Kickass if one of the proxies is up
|
|
|
+ if ($search_url) {
|
|
|
+ my %tmp = (
|
|
|
+ 'host' => $host,
|
|
|
+ 'search_url' => $search_url,
|
|
|
+ 'search_suffix' => '/',
|
|
|
+ 'weight' => 0.30,
|
|
|
+ 'quote' => 1
|
|
|
+ );
|
|
|
+ $SOURCES{'KICK'} = \%tmp;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
# Sanity check
|
|
|
if (scalar(keys(%SOURCES)) < 1) {
|
|
|
die("No sources available\n");
|
|
|
@@ -523,11 +556,20 @@ foreach my $url (@urls) {
|
|
|
}
|
|
|
sleep($DELAY * (rand(2) + 0.5));
|
|
|
$fetch->url($url);
|
|
|
- $fetch->fetch();
|
|
|
+ $fetch->fetch('nocheck' => 1);
|
|
|
+
|
|
|
+ # Check for useful errors
|
|
|
+ if ($fetch->status_code() == 404) {
|
|
|
+ if ($DEBUG) {
|
|
|
+ print STDERR "Skipping content from 404 response\n";
|
|
|
+ }
|
|
|
+ next;
|
|
|
+ }
|
|
|
|
|
|
# Check for errors
|
|
|
if ($fetch->status_code() != 200) {
|
|
|
print STDERR 'Error fetching URL: ' . $url . "\n";
|
|
|
+ next;
|
|
|
}
|
|
|
|
|
|
# Save the content, discriminating by data type
|
|
|
@@ -628,11 +670,12 @@ foreach my $content (@html_content) {
|
|
|
|
|
|
# Split each TD element from the row
|
|
|
my @tds = split(/\<td(?:\s+[^\>]*)?\>/i, $tr);
|
|
|
- if (scalar(@tds) != 10) {
|
|
|
+ my $numCols = scalar(@tds) - 1;
|
|
|
+ if ($numCols > 9 && $numCols < 8) {
|
|
|
print STDERR 'Invalid ISO TR: ' . $tr . "\n";
|
|
|
next;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
# Skip sponsored results
|
|
|
if ($tds[1] =~ /Sponsored\<\/td\>/i) {
|
|
|
if ($DEBUG > 1) {
|
|
|
@@ -697,6 +740,82 @@ foreach my $content (@html_content) {
|
|
|
push(@tors, \%tor);
|
|
|
}
|
|
|
|
|
|
+ } elsif ($content =~ /KickassTorrents\<\/title\>/i) {
|
|
|
+
|
|
|
+ # Find each TR element from Kickass
|
|
|
+ my @trs = splitTRs($content);
|
|
|
+ foreach my $tr (@trs) {
|
|
|
+
|
|
|
+ # Split each TD element from the row
|
|
|
+ my @tds = split(/\<td(?:\s+[^\>]*)?\>/i, $tr);
|
|
|
+ my $numCols = scalar(@tds) - 1;
|
|
|
+ if ($numCols > 9 && $numCols < 8) {
|
|
|
+ print STDERR 'Invalid KICK TR: ' . $tr . "\n";
|
|
|
+ next;
|
|
|
+ }
|
|
|
+
|
|
|
+ # Find the torrent title
|
|
|
+ my ($title) = $tds[1] =~ /\<a(?:\s+[^\>]*)?href\=\"[^\"]+\?title\=\[[^\]\"]+\]([^\"]+)\"/i;
|
|
|
+ if (!defined($title) || length($title) < 1) {
|
|
|
+ if ($DEBUG) {
|
|
|
+ print STDERR "Unable to find torrent title in TD:\n\t" . $tds[1] . "\n";
|
|
|
+ }
|
|
|
+ next;
|
|
|
+ }
|
|
|
+ $title =~ s/^\s+//;
|
|
|
+
|
|
|
+ # Find the torrent URL
|
|
|
+ my ($url) = $tds[1] =~ /\<a(?:\s+[^\>]*)?href=\"(magnet:[^\"]+)\"/i;
|
|
|
+ if (!defined($url) || length($url) < 1) {
|
|
|
+ if ($DEBUG) {
|
|
|
+ print STDERR "Unable to find torrent URL in TD:\n\t" . $tds[1] . "\n";
|
|
|
+ }
|
|
|
+ next;
|
|
|
+ }
|
|
|
+
|
|
|
+ # Extract the season and episode numbers
|
|
|
+ my ($fileSeason, $episode) = findSE($title);
|
|
|
+
|
|
|
+ # Extract the size
|
|
|
+ my $size = 0;
|
|
|
+ my $unit = 'M';
|
|
|
+ if ($tds[2] =~ m/(\d+(?:\.\d+)?)\s+\<span\>(G|M)B\<\/span\>\<\/td\>/i) {
|
|
|
+ $size = $1;
|
|
|
+ $unit = $2;
|
|
|
+ }
|
|
|
+ if ($unit eq 'G') {
|
|
|
+ $size *= 1024;
|
|
|
+ }
|
|
|
+ $size = int($size);
|
|
|
+
|
|
|
+ # Count the sum of seeders and leachers
|
|
|
+ my $seeds = 0;
|
|
|
+ if ($tds[5] =~ /(\d+)\<\/td\>/i) {
|
|
|
+ $seeds = $1;
|
|
|
+ }
|
|
|
+ my $leaches = 0;
|
|
|
+ if ($tds[6] =~ /(\d+)\<\/td\>/i) {
|
|
|
+ $leaches = $1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($DEBUG) {
|
|
|
+ print STDERR 'Found file (' . $title . '): ' . $url . "\n";
|
|
|
+ }
|
|
|
+
|
|
|
+ # Save the extracted data
|
|
|
+ my %tor = (
|
|
|
+ 'title' => $title,
|
|
|
+ 'season' => $fileSeason,
|
|
|
+ 'episode' => $episode,
|
|
|
+ 'seeds' => $seeds,
|
|
|
+ 'leaches' => $leaches,
|
|
|
+ 'size' => $size,
|
|
|
+ 'url' => $url,
|
|
|
+ 'source' => 'KICK'
|
|
|
+ );
|
|
|
+ push(@tors, \%tor);
|
|
|
+ }
|
|
|
+
|
|
|
} else {
|
|
|
print STDERR "Unknown HTML content:\n" . $content . "\n\n";
|
|
|
}
|
|
|
@@ -746,13 +865,20 @@ foreach my $tor (@tors) {
|
|
|
}
|
|
|
next;
|
|
|
|
|
|
- # Skip german files
|
|
|
+ # Skip German files
|
|
|
} elsif ($tor->{'title'} =~ /german/i) {
|
|
|
if ($DEBUG) {
|
|
|
print STDERR 'Skipping file: Title contains "german": ' . $tor->{'title'} . "\n";
|
|
|
}
|
|
|
next;
|
|
|
|
|
|
+ # Skip French files
|
|
|
+ } elsif ($tor->{'title'} =~ /french/i) {
|
|
|
+ if ($DEBUG) {
|
|
|
+ print STDERR 'Skipping file: Title contains "french": ' . $tor->{'title'} . "\n";
|
|
|
+ }
|
|
|
+ next;
|
|
|
+
|
|
|
# Skip unedited files
|
|
|
} elsif ($tor->{'title'} =~ /unedited/i) {
|
|
|
if ($DEBUG) {
|