2

Do you know of any easy to use, neat API for Python or Perl to interact with BitTorrent Trackers? E.g., I take a torrent file, enumerate all trackers in the file and ask the tracker for the statistics of the peers related with the downloaded file?

BitTorrent Tracker specification is not too complicated, but I don't want to reinvent the wheel :)

Note that I don't want to download the data, just to grab some stats (Net::BitTorrent far more than I need)

Jakub M.
  • 32,471
  • 48
  • 110
  • 179

3 Answers3

3

Just plain command line isn't enough? :-) (Transmission) gives you transmission-remote tool which permits to enumerate trackers and get peer statistics with one command. Look on

     -pi --peer-info
         List the current torrent's connected peers.  In the `status' section of the list, the following shorthand is used:
               D: Downloading from this peer
               d: We would download from this peer if they would let us
               E: Encrypted connection
               I: Peer is an incoming connection
               K: Peer has unchoked us, but we're not interested
               O: Optimistic unchoked
               U: Uploading to peer
               u: We would upload to this peer if they asked
               X: Peer was discovered through Peer Exchange (PEX)
               ?: We unchoked this peer, but they're not interested
...

     -si --session-info
         List session information from the server

Well, to use it you have to use transmission as your torrent client, but if you do then you can do it with grep, it depends on what really you want to achieve.

Konstantin
  • 113
  • 6
  • It is not in the standard Ubuntu package: `apt-get install transmission-cli transmission-common transmission-daemon`. _transmission-show_ is also useful – Jakub M. Jul 27 '11 at 13:05
  • 1
    Issue: _transmission-remote_ gives `Unexpected response:

    401: Unauthorized

    Unauthorized Useroded` error even though the tracker does not need authentication...
    – Jakub M. Jul 27 '11 at 13:22
  • 1
    It's not tracker's issue - check the documentation about configuring access lists in configuration of the daemon and access right for remote management, maybe you just want to turn them off? Check settings.json in ~/.config/transmission or /etc/transmission-daemon (depends on how do you launch it) for rpc-* options. Attention, just editing config in /etc isn't enough if you run it as daemon - you'll need to do service transmission-daemon reload as it quietly overwrites settings.conf on exit. To check if you can use rpc visit localhost:9091 by default – Konstantin Jul 27 '11 at 13:54
  • And surely try transmission-remote host:9091 --auth=username:password -l (username and password are configured from transmission interface or via settings.json) – Konstantin Jul 27 '11 at 14:00
2

Have a look at py-transmission

Edit: Since I wrote this, I found that transmissionbt's RPC interface is extremely well documented and user friendly enough if you take the time to learn the basics.

Andrejas
  • 3,733
  • 1
  • 16
  • 9
1

I made the Perl script to get data from .torrent files, pool the trackers and get some statistics (file hash, IP connected to the tracker, file size, etc.). No big science, just some Perl-fu. To run it, you need: Perl module Bencode, curl and transmission-show installed. Debug garbage is sent to stderr and the proper output to 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";
                }
            }
        }
    }
}
Jakub M.
  • 32,471
  • 48
  • 110
  • 179
  • 1
    Take a look on https://forum.transmissionbt.com/viewtopic.php?f=1&t=9085 - they tried to apply script like yours to implement queueing for transmission. – Konstantin Jul 28 '11 at 10:29