Is there a PHP module that you can use to programmatically read a torrent to find out information about it, Seeders for instance?
Google comes up with this PHP client on sourceforge and this torrent class on PHP classes. Should be all you need.
Torrent files are basically nested dictionaries encoded with BEncode. BEncode is a simple encoding and there are a few BDecode PHP classes, like this one.
Structure of torrent file is described in BEP0003.
Note that torrent files don't contain "Seeders" field that you mention. The list of seeders is dynamic and is managed by tracker server. Having torrent's hash_info
and tracker_url
(both available from torrent file) you can send scrape-request to the tracker and it will return number of seeders in 'complete' field, see Tracker Scrape Convention.
I have used these functions in a small website I made once. Think I found them with a php bittorrent tracker called OpenTracker or something, but can't find the website...
You wont find the seeders in the torrent file though. The torrent file just contain info about the files, hash codes and lengths etc. And some tracker information I believe. How many seeders and such you will have to get from the tracker. You can read about the protocal at BitTorrent.org. The communication is, I believe, bencoded, so you can use these functions for that as well. Which means you just have to figure out what to send to get what you want back.
NOTE: I did not write these three functions. Like I said, I found them in the source of an open source torrent tracker. The functions are not commented, but the function names together with a print_r on the result of a torrent file you know the info inshould be enough to understand how to use them. I added some example code at the bottom to show how I used them. And they worked.
function bdecode($str) {
$pos = 0;
return bdecode_r($str, $pos);
}
function bdecode_r($str, &$pos) {
$strlen = strlen($str);
if (($pos < 0) || ($pos >= $strlen)) {
return null;
}
else if ($str{$pos} == 'i') {
$pos++;
$numlen = strspn($str, '-0123456789', $pos);
$spos = $pos;
$pos += $numlen;
if (($pos >= $strlen) || ($str{$pos} != 'e')) {
return null;
}
else {
$pos++;
return intval(substr($str, $spos, $numlen));
}
}
else if ($str{$pos} == 'd') {
$pos++;
$ret = array();
while ($pos < $strlen) {
if ($str{$pos} == 'e') {
$pos++;
return $ret;
}
else {
$key = bdecode_r($str, $pos);
if ($key == null) {
return null;
}
else {
$val = bdecode_r($str, $pos);
if ($val == null) {
return null;
}
else if (!is_array($key)) {
$ret[$key] = $val;
}
}
}
}
return null;
}
else if ($str{$pos} == 'l') {
$pos++;
$ret = array();
while ($pos < $strlen) {
if ($str{$pos} == 'e') {
$pos++;
return $ret;
}
else {
$val = bdecode_r($str, $pos);
if ($val == null) {
return null;
}
else {
$ret[] = $val;
}
}
}
return null;
}
else {
$numlen = strspn($str, '0123456789', $pos);
$spos = $pos;
$pos += $numlen;
if (($pos >= $strlen) || ($str{$pos} != ':')) {
return null;
}
else {
$vallen = intval(substr($str, $spos, $numlen));
$pos++;
$val = substr($str, $pos, $vallen);
if (strlen($val) != $vallen) {
return null;
}
else {
$pos += $vallen;
return $val;
}
}
}
}
function bencode($var) {
if (is_int($var)) {
return 'i' . $var . 'e';
}
else if (is_array($var)) {
if (count($var) == 0) {
return 'de';
}
else {
$assoc = false;
foreach ($var as $key => $val) {
if (!is_int($key)) {
$assoc = true;
break;
}
}
if ($assoc) {
ksort($var, SORT_REGULAR);
$ret = 'd';
foreach ($var as $key => $val) {
$ret .= bencode($key) . bencode($val);
}
return $ret . 'e';
}
else {
$ret = 'l';
foreach ($var as $val) {
$ret .= bencode($val);
}
return $ret . 'e';
}
}
}
else {
return strlen($var) . ':' . $var;
}
Some example usage:
# Read a file
$content = file_get_contents("file.torrent");
$content_d = bdecode($content);
# Check if bdecode succeeded
if(empty($content_d)) exit('Something is wrong with the torrent. BDecode failed.');
# Calculate info_hash
$info_hash = sha1(bencode($content_d['info']), true);
# Calculate length
$length = 0;
function add_length($value, $key)
{
global $length;
if($key == 'length') $length += $value;
}
array_walk_recursive($content_d, 'add_length');