I make WordPress and MyBB plugins on request! Check my Plugin Development page.

How to Create a Torrent Tracker: Part 3 – Torrent and User Details

BitTorrent, Programming, Web Development 15 August 2009 | 6 Comments

In this third part of the tutorial, our goal is to show some information about our torrents and users. We’ll go through a bunch of tips and snippets that any developer may find useful while developing a torrent site, such as some util functions to display relative times, friendly sizes and a tree with files and folders.

A look at files tables

xbt_files, the table which contains records for all tracked torrents, gives us access to some information we’ll need to show on our torrent details page:

  • info_hash Info hash of the torrent
  • leechers/seeders Explains itself. Number of current leechers/seeders
  • completed Number of times this torrent has been 100% downloaded by a peer
  • mtime Last time this torrent has been updated as Unix timestamp
  • ctime Time this torrent has been added to the tracker as Unix timestamp
  • flags When this value is set to 1, XBTT will stop tracking the torrent and delete its record (we won’t need it here)

Our ideal details page will display those values in a cool box or table. The nicest way to display those time values is using a function that shows them as a relative time string. You may want to use this snippet at Snipplr.

The xbt_files_users table stores a torrent-user map for each torrent entry with information on peer activity.

  • fid torrent ID
  • uid user ID
  • active whether this activity is still going on
  • announced Number of announces
  • completed Number of 100% complete transfers
  • downloaded/left/uploaded Downloaded, left, uploaded bytes
  • mtime Last update time

What we’ve just seen is all data related to peer activity. As well as this kind of stuff, we may want to display .torrent files details, just like any other torrent site does (just see the Details tab on any Minonova torrent). We’re going to look at some code to get this data and display it in a friendly way.

Getting .torrent metadata

In the previous part we’ve seen how to open a .torrent file and have access to bencoded values through File_Bittorrent2. The following code snippets will make use of this library.
First of all, we have to locate the .torrent file we want to open. If we have stored them using torrent IDs as filenames (as we’ve done in part 2), opening the file is as easy as those lines:

<?php
define(‘TORRENT_UPLOAD_PATH’,‘uploads’);

$filename=TORRENT_UPLOAD_PATH.$id.‘.torrent’;
$dec=new File_Bittorrent2_Decode;
$info=$dec->decodeFile($filename);
?>

To display sizes we will use this handy function:

<?php
function mksize($bytes)
{
        if ($bytes < 1000 * 1024)
                return number_format($bytes / 1024, 2) . " kB";
        if ($bytes < 1000 * 1048576)
                return number_format($bytes / 1048576, 2) . " MB";
        if ($bytes < 1000 * 1073741824)
                return number_format($bytes / 1073741824, 2) . " GB";
        if ($bytes < 1000 * 1099511627776)
                return number_format($bytes / 1099511627776, 2) . " TB";
        if ($bytes < 1000 * 1125899906842620)
                return number_format($bytes / 1125899906842620, 2) . " PB";
        if ($bytes < 1000 * 1152921504606850000)
                return number_format($bytes / 1152921504606850000, 2) . " EB";
}
?>

Now we’re ready to show the stuff we need:

Filename: <?php echo $filename ?>
Info hash <?php echo $info[‘info_hash’] ?>
Total size <?php echo mksize($info[’size’]) ?> in <?php echo count($info[‘files’]) ?> files

Torrent files tree

In order to display the files contained in our torrent, we’re going to output a file-tree including directories. As we have noticed, $info['files'] is an array containing all the files in the torrent. They are stored as paths, for example “directory/file1.txt”, “directory/file2.txt”, and so on, so, in order to build a tree, we need to separate directories from filenames and put them in a multidimensional array first. This is done by the following code.

<?php
function buildTreeArray($files)
{
    $ret = array();

    foreach ($files as $k => $v)
    {
        $filename=$v[‘filename’];

        $parts = preg_split(‘/\//’, $filename, -1, PREG_SPLIT_NO_EMPTY);
        $leaf = array_pop($parts);

        // build parent structure
        $parent = &$ret;
        foreach ($parts as $part)
        {
                $parent = &$parent[$part];
        }

        if (empty($parent[$leaf]))
        {
                $v[‘filename’]=$leaf;
                $parent[$leaf] = $v;
        }
    }

    return $ret;
}
?>

This function will loop through each file, split directories from filenames and organize them in a new array, which we can now display in a barebones HTML tree using a recursive function. Of course you will have to customize it using HTML/CSS or whatever and maybe add an appropriate icon before each file based on its extension; I’ll leave that to your creativity. Comments should be self-explanatory.

<?php
function outputTree($files, $indent=0)
{
    echo "<ul>";

    foreach($files as $k=>$v)
    {
        $entry=isset($v[‘filename’]) ? $v[‘filename’] : $k;
        $size=$v[’size’];

        if($indent==0)
        {
            // root
            $is_folder=true;
        }
        elseif(is_array($v) && (!array_key_exists(‘filename’,$v) && !array_key_exists(’size’,$v)))
        {
            // normal node
            $is_folder=true;
        }
        else
        {
            // leaf node, i.e. a file
        $is_folder=false;
        }

        if($is_folder)
        {
            // we could output a folder icon here
        }
        else
        {
            // we could output an appropriate icon
            // based on file extension here
            $ext=pathinfo($entry,PATHINFO_EXTENSION);
        }

        echo "<li>";
        echo $entry; // output folder name or filename

        if(!$is_folder)
        {
            // if it’s not a folder, show file size
            echo " (".mksize($size).")";
        }

        echo "</li>";
 
        if(is_array($v) && $is_folder)
        {
            outputTree($v, ($indent+1));
        }
    }

    echo "</ul>";
}
?>

Some user data

Now that we are done with torrent data, there is nothing left to show but some user details in profiles.
We need to fetch data from xbt_users, which contains trivial stuff like downloaded and uploaded bytes.
An important thing to show is the user ratio, which can be calculated by simply dividing uploaded by downloaded.

<?php
function get_ratio($ul,$dl)
{
    if($dl<=0 || $ul<=0)
        return ‘-’;

    return $ratio=round($ul/$dl, 2);
}
?>

Conclusion

This time we have looked at the structure of some XBTT tables which store information about tracker and torrent data. Also, we’ve fetched metadata from .torrent files and shown some snippets to output them in a nice and friendly way. I hope this helps out someone in speeding up development of new custom made torrent sites. Stay tuned for the following parts of the guide!

Tagged in , , , ,

6 Responses on “How to Create a Torrent Tracker: Part 3 – Torrent and User Details”

  1. Mantis says:

    Hi, great guide! I think I’m going to follow all of this through since I would like to add some torrents to my site, to reduce the bandwidth load. Awaiting further tutorials eagerly.

  2. Bypasser says:

    Ok!

    Thank you very much for all this information.
    Something I don’t understand: if the tracker is public, and people don’t have to use ‘our’ tracker – with this code we will only get data about the torrents present on our tracker, don’t we? (As it is based on the database and note a scrape of tracker)

    So as you keep the possibility of an open site in the comments of the code: do you know an easy way to scrape data for ‘outside trackers’ torrents?

    Thank you anyway, all that is great…

    Have a nice life!

    bp

  3. Bypasser says:

    (corrected email so that you can reply by email if you want)
    Ok!

    Thank you very much for all this information.
    Something I don’t understand: if the tracker is public, and people don’t have to use ‘our’ tracker – with this code we will only get data about the torrents present on our tracker, don’t we? (As it is based on the database and note a scrape of tracker)

    So as you keep the possibility of an open site in the comments of the code: do you know an easy way to scrape data for ‘outside trackers’ torrents?

    Thank you anyway, all that is great…

    Have a nice life!

    bp

  4. Hangman says:

    @Bypasser: as far as I know, a scrape file is just a bencoded dictionary which you can parse through a script. I’m sure there’s some example around the web, although if you are familiar with PHP you could code your own script with ease using an existing parser class.

  5. Bypasser says:

    An going slowly in my project, will try to do this scraper.

    Thank you for your reply & for your posts.

    Have a nice life,

    B.

Trackbacks/Pingbacks

Leave a Reply