#!/opt/bin/perl BEGIN { $ENV{http_proxy} = $ENV{https_proxy} = "http://127.0.0.1:8118"; # privoxy } use common::sense; use Compress::LZF; use EV; use AnyEvent::HTTP; use BDB; use Coro; use Coro::BDB; use AnyEvent::DNS; use Set::IntSpan; use CBOR::XS; use Compress::Zlib (); use Compress::Raw::Zlib (); use AnyEvent::TLS; BDB::min_parallel 8; #our @TPB = qw(https://thepiratebay.org); #our @TPB = qw(https://baypirateproxy.org); our @TPB = qw(http://uj3wazyk5u4hnvtk.onion); our $TPB = $TPB[0]; our $TODAY = int time / 86400; #our $TPB_SWITCHER = AE::timer 1, 0.02, sub { # state $i; # $TPB = $TPB[++$i % @TPB]; #}; ############################################################################# $AnyEvent::HTTP::MAX_PER_HOST = $AnyEvent::HTTP::MAX_PERSISTENT_PER_HOST = 400; our %stat; our $statprint = AE::timer 1, 1, sub { syswrite STDOUT, "\r" . (join " ", map "$_=$stat{$_}", sort keys %stat) . " " if $ENV{VERBOSE}; }; our @DICTIONARY = (do { open my $fh, "<:perlio", "dictionary0" or die "dictionary0: $!"; local $/; <$fh> }); ############################################################################# our $db_env = db_env_create; $db_env->set_flags (BDB::AUTO_COMMIT | BDB::TXN_WRITE_NOSYNC, 1); $db_env->log_set_config (BDB::LOG_AUTO_REMOVE); #$db_env->set_cachesize (0, 8 * 1024 * 1024); $db_env->set_cachesize (0, 512 * 1024); $db_env->set_lk_max_lockers (20480); $db_env->set_lk_max_locks (20480); $db_env->set_lk_max_objects (20480); mkdir "db", 0777; db_env_open $db_env, "db", BDB::INIT_LOCK | BDB::INIT_LOG | BDB::INIT_MPOOL | BDB::INIT_TXN | BDB::RECOVER | BDB::REGISTER | BDB::USE_ENVIRON | BDB::CREATE, 0666; our %DB; sub table($) { my $db = $DB{$_[0]} = db_create $db_env; db_open $db, undef, $_[0], undef, BDB::BTREE, BDB::AUTO_COMMIT | BDB::CREATE, 0666; die if $!; $db } our $db_state = table "state"; # global state our $db_info = table "info"; # per torrent state our $TXN; sub get($$) { db_get $_[0], $TXN, $_[1], my $data, 0; $data # will be undef on error } sub put($$$) { db_put $_[0], $TXN, $_[1], $_[2], 0; } sub del($$) { db_del $_[0], $TXN, $_[1], 0, sub { }; } sub sget($) { get $db_state, $_[0] } sub sput($$) { put $db_state, $_[0], $_[1]; } sub iget($) { my $data = get $db_info, $_[0]; length $data ? decode_cbor $data : [] } sub iput($$) { put $db_info, $_[0], encode_cbor $_[1]; } our $syncer = AE::timer 5, 60, sub { db_env_txn_checkpoint $db_env, 0, 0, 0, sub { }; }; sub dbsync() { db_env_txn_checkpoint $db_env; } sub dbflush { return if $::dbflush_called++; db_env_txn_checkpoint $db_env, sub { }; BDB::set_sync_prepare undef; db_close $_ for values %DB; db_env_txn_checkpoint $db_env; db_env_close $db_env; } END { dbflush; } sub quit { EV::unloop; #exit 1; }; our $sigint = AE::signal INT => \&quit; our $sigterm = AE::signal TERM => \&quit; sub dic_compress($$) { my $d = new Compress::Raw::Zlib::Deflate -Level => 9, -WindowBits => -15, -Dictionary => $DICTIONARY[$_[0]], -AppendOutput => 1, ; my $o; $d->deflate ($_[1], $o); $d->flush ($o); $o } sub dic_decompress($$) { my $i = new Compress::Raw::Zlib::Inflate -WindowBits => -15, -Dictionary => $DICTIONARY[$_[0]], -AppendOutput => 1, -ConsumeInput => 0, ; $i->inflate ($_[1], my $o, 1); $o } ############################################################################# ############################################################################# sub GET { my ($data, $hdr); for (1..50) { http_get $_[0], #proxy => undef, recurse => 0, headers => { "user-agent" => "Mozilla/5.0 (X11; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0 Iceweasel/20.0", "referer" => undef, }, Coro::rouse_cb; ($data, $hdr) = Coro::rouse_wait; $hdr->{Status} = 404 if $data =~ /You're looking for something that does not, has not, will not, might not or must not exist/; $hdr->{Status} = 580 if $data =~ /^(?:Upgrading software|Could not connect to caching server|Database maintenance, please check back in 10 minutes)/; $hdr->{Status} = 581 unless length $data; $data = Compress::Zlib::memGunzip $data if $hdr->{"content-encoding"} eq "gzip"; last if $hdr->{Status} < 500; Coro::AnyEvent::sleep 1.5 if $hdr->{Satus} == 503; Coro::AnyEvent::sleep 9.5 if $hdr->{Satus} == 580; Coro::AnyEvent::sleep 0.5; ++$stat{"retry-$hdr->{Status}"}; # use Data::Dump; ddx $hdr;#d# } ++$stat{$hdr->{Status}}; ($data, $hdr) } 1