Я создал скрипт Perl для получения данных из файлов .torrent, объединения трекеров и получения некоторой статистики (хэш файла, IP-адрес, связанный с трекером, размер файла и т. Д.). Никакой большой науки, только немного Perl-fu. Для его запуска вам понадобятся: Perl-модуль Bencode , curl и Transmission-Show . Отладочный мусор отправляется на stderr , а правильный вывод на stdout .
#!/usr/bin/perl
use Bencode qw( bencode bdecode );
use Data::Dumper;
use warnings;
use strict;
my $G_PEER_ID = "hfgdbvnchdgfhvnfbghf";
my $G_MAX_TIME = 20;
sub peer_decode
{
my $d = shift;
my @a = split '', $d;
# printf ">>%d %d<<\n", length($d), scalar(@a);
my @ret;
while(@a) {
my $ip = sprintf "%d.%d.%d.%d" ,
unpack('C',shift(@a)),
unpack('C',shift(@a)),
unpack('C',shift(@a)),
unpack('C',shift(@a));
my $port = sprintf "%d", 256 * unpack('C',shift(@a))
+ unpack('C',shift(@a));
# printf "%d $ip $port\n",scalar(@a);
push @ret, $ip;
}
return \@ret;
}
sub get_tracker_data_from_file
{
my $fname = shift;
my $ret = {};
my $c = `transmission-show $fname`;
print STDERR "$c\n";
if ( $c =~ /^\s+Hash:\s*(\S+)/mg ) {
$ret->{'hash'} = $1;
}
if ( $c =~ /^\s+Total Size:\s*(.+)$/mg ) {
$ret->{'size'} = $1;
}
my @g;
@g = ($c =~ /Tier \#\d+[\n\r\s]+(\S+)/gm);
if ( @g ) {
$ret->{'tiers'} = \@g;
}
return $ret;
}
sub get_peer_ips
{
my $hash = shift;
my $tracker = shift;
my $ret = undef;
$hash =~ s/(..)/\%$1/g;
$tracker =~ s/\/$//;
my $c = "curl -m $G_MAX_TIME -s '$tracker?info_hash=$hash&peer_id=$G_PEER_ID&uploaded=0&downloaded=0&left=1'";
print STDERR "$c\n";
my $w = `$c`;
return undef if not $w;
printf STDERR "%s\n" , Dumper($w);
return undef if $w =~ /<\s*html\s*>/gi;
$w = bdecode($w, 1);
if ( defined $w->{'peers'} ) {
$ret = peer_decode($w->{'peers'});
}
return $ret;
}
# -- main
my @files = @ARGV;
if ( not @files ) {
print <<END
usage: $0 <file1.torrent> <file2.torrent> ...
(c) http://stackoverflow.com/users/497208
END
}
for my $fname ( @files ) {
printf STDERR "File: %s\n", $fname;
my $tr = get_tracker_data_from_file($fname);
printf STDERR "%s\n", Dumper $tr;
my $hash = undef;
$hash = $tr->{'hash'} if defined $tr->{'hash'};
exit if not defined $hash;
my $size = undef;
if ( defined $tr->{'size'} ) {
$size = $tr->{'size'};
}
else {
$size = "?";
}
if ( defined $tr->{'tiers'} ) {
# shift @{$tr->{'tiers'}} for (1..5);
for my $tracker ( @{$tr->{'tiers'}} ) {
my $ips = get_peer_ips( $hash, $tracker);
printf STDERR "%s\n", Dumper $ips;
if ( defined $ips ) {
for my $ip ( @$ips ) {
my $c = sprintf "%s; %16s; %s; %s", $hash, $ip, $size, $tracker;
printf STDERR "$c\n";
printf "$c\n";
}
}
}
}
}