First of all I would ask the developers to PLEASE add the start/stop all feature in the next release of torrentflux, it's a very useful addition that most major multi-torrent clients worth their salt have already. If not then at least assign the torrent starting functionality to a function of it's own rather than having it in the index.php where it can't be reused without copy/pasting.
This hack adds start all/stop all functionality to torrentflux 2.1 to allow a logged in admin user to start/stop all torrents with one click of a button. The start/stop all buttons are added towards the bottom right of the main index page, just above the section that indicates the current down/upload speeds.
Only torrents that have already been started at least once can be affected by the start/stop all buttons - to start torrents that haven't already been started would need a slightly different approach. It's not always a good idea to blindly start all torrents in the torrent list, at least not for me anyway. I use the start stop all functionality from a cronjob to stop all torrents at 6pm and then restart them all at midnight. However I also have a utility that imports torrents automatically as well and I don't necessarily always want to start all of these before I've checked them over. The best thing would be to have a setting in the control panel to allow the user to 'start/stop all torrents including NEW torrents'. Again though that's one for the feature request list really in a future version of tf.
Ok on to the mod...
---
1. Find the line in index.php that reads:
$drivespace = getDriveSpace($cfg["path"]);
and modify it to read:
$drivespace = getDriveSpace($cfg["path"]);
// Did the user issue the stop all command?
if(isset($_REQUEST["stopall"]) && IsAdmin($cfg["user"]) === true) {
include_once("AliasFile.php");
$dirName = $cfg["torrent_file_path"];
$arList = array();
$file_filter = getFileFilter($cfg["file_types_array"]);
$handle = opendir($dirName);
while($entry = readdir($handle)) {
if ($entry != "." && $entry != ".." && !is_dir($dirName."/".$entry)) {
if (ereg($file_filter, $entry)) {
$key = filemtime($dirName."/".$entry).md5($entry);
$arList[$key] = $entry;
}
}
}
foreach($arList as $entry) {
$owner = getOwner($entry);
$alias = getAliasName($entry);
$af = new AliasFile($cfg["torrent_file_path"].$alias.".stat", $owner);
if ($af->running != "2" && $af->time_left != "Torrent Died") {
if($af->percent_done < 100) {
// The torrent is being stopped but is not completed dowloading
$af->percent_done = ($af->percent_done + 100)*-1;
$af->running = "0";
$af->time_left = "Torrent Stopped";
} else {
// Torrent was seeding and is now being stopped
$af->percent_done = 100;
$af->running = "0";
$af->time_left = "Download Succeeded!";
}
// Write out the new Stat File
$af->WriteFile();
}
}
// pause to let stat files catch up:
sleep(5);
AuditAction("ADMIN", "Stopped All Torrents");
header("location: index.php");
}
// Did the user issue the resume all command?
if(isset($_REQUEST["startall"]) && IsAdmin($cfg["user"]) === true) {
include_once("AliasFile.php");
// check to see if the path to the python script is valid
if (!is_file($cfg["btphpbin"]))
{
AuditAction($cfg["constants"]["error"], "Error Path for ".$cfg["btphpbin"]." is not valid");
if (IsAdmin())
{
header("location: admin.php?op=configSettings");
exit();
}
else
{
$messages .= "<b>Error</b> TorrentFlux settings are not correct (path to python script is not valid) -- please contact an admin.<br>";
}
}
$command = "";
$rate = getRequestVar('rate');
if (empty($rate))
{
$rate = $cfg["max_upload_rate"];
}
$drate = getRequestVar('drate');
if (empty($drate))
{
$drate = $cfg["max_download_rate"];
}
$superseeder = getRequestVar('superseeder');
if (empty($superseeder))
{
$superseeder = "0"; // should be 0 in most cases
}
$runtime = getRequestVar('runtime');
if (empty($runtime))
{
$runtime = $cfg["torrent_dies_when_done"];
}
$maxuploads = getRequestVar('maxuploads');
if (empty($maxuploads))
{
$maxuploads = $cfg["max_uploads"];
}
$minport = getRequestVar('minport');
if (empty($minport))
{
$minport = $cfg["minport"];
}
$maxport = getRequestVar('maxport');
if (empty($maxport))
{
$maxport = $cfg["maxport"];
}
$rerequest = getRequestVar("rerequest");
if (empty($rerequest))
{
$rerequest = $cfg["rerequest_interval"];
}
$sharekill = getRequestVar('sharekill');
if ($runtime == "True" )
$sharekill = "-1";
if (empty($sharekill))
{
$sharekill = $cfg["sharekill"];
}
// Build up a list of torrents to start, $arList:
$dirName = $cfg["torrent_file_path"];
$arList = array();
$file_filter = getFileFilter($cfg["file_types_array"]);
$handle = opendir($dirName);
$command = "";
while($entry = readdir($handle)) {
if ($entry != "." && $entry != ".." && !is_dir($dirName."/".$entry)) {
if (ereg($file_filter, $entry)) {
$key = filemtime($dirName."/".$entry).md5($entry);
$arList[$key] = $entry;
}
}
}
// For each torrent, if not running start it now:
foreach($arList as $entry) {
$owner = getOwner($entry);
$alias = getAliasName($entry);
$af = new AliasFile($cfg["torrent_file_path"].$alias.".stat", $owner);
if ($af->running == 0 ) {
$af->StartTorrentFile(); // this only writes out the stat file (does not start torrent)
if (usingTornado())
{
$command = $runtime." ".$sharekill." ".$cfg["torrent_file_path"].$alias.".stat ".$owner." --responsefile '".$cfg["torrent_file_path"].$entry."' --display_interval 5 --max_download_rate ". $drate ." --max_upload_rate ".$rate." --max_uploads ".$maxuploads." --minport ".$minport." --maxport ".$maxport." --rerequest_interval ".$rerequest." --super_seeder ".$superseeder;
if(file_exists($cfg["torrent_file_path"].$alias.".prio")) {
$priolist = explode(',',file_get_contents($cfg["torrent_file_path"].$alias.".prio"));
$priolist = implode(',',array_slice($priolist,1,$priolist[0]));
$command .= " --priority ".$priolist;
}
$command .= " ".$cfg["cmd_options"]." > /dev/null &";
if (! array_key_exists("pythonCmd", $cfg))
{
insertSetting("pythonCmd","/usr/bin/python");
}
if (! array_key_exists("debugTorrents", $cfg))
{
insertSetting("debugTorrents", "0");
}
if (!$cfg["debugTorrents"])
{
$pyCmd = $cfg["pythonCmd"] . " -OO";
}else{
$pyCmd = $cfg["pythonCmd"];
}
$command = "cd " . $cfg["path"] . $owner . "; HOME=".$cfg["path"]."; export HOME; nohup " . $pyCmd . " " .$cfg["btphpbin"] . " " . $command;
}
else
{
$messages .= "<b>Error</b> BitTornado is only supported Client at this time.<br>";
}
// write the session to close so older version of PHP will not hang
session_write_close("TorrentFlux");
// Start command safely:
$result=shell_exec($command);
AuditAction($cfg["constants"]["start_torrent"], $torrent."<br>Die:".$runtime.", Sharekill:".$sharekill.", MaxUploads:".$maxuploads.", DownRate:".$drate.", UploadRate:".$rate.", Ports:".$minport."-".$maxport.", SuperSeed:".$superseeder.", Rerequest Interval:".$rerequest);
// slow down and wait for thread to kick off.
// otherwise on fast servers it will kill stop it before it gets a chance to run.
sleep(1);
}
if ($messages != "")
{
AuditAction($cfg["constants"]["error"], $messages);
}
}
// Finally redirect to index page:
header("location: index.php");
}
2. Towards the end of index.php find this:
<table>
<tr>
<td class="tiny" align="right"><?php echo _CURRENTDOWNLOAD ?>:</td>
<td class="tiny"><strong><?php echo number_format($cfg["total_download"], 2); ?></strong> kB/s</td>
</tr>
and modify it to read:
<table>
<?php
if(IsAdmin()) {
?>
<tr>
<td class="tiny" align="right">Start/Stop All Torrents: </td>
<td class="tiny"><a href="?stopall=now"><img src="images/kill.gif" title="Stop all torrents" border="0" /></a> <a href="?startall=now"><img src="images/run_on.gif" title="Start all torrents" border="0" alt="Start/Resume All Torrents"></a></td>
</tr>
<?php
}
?>
<tr>
<td class="tiny" align="right"><?php echo _CURRENTDOWNLOAD ?>:</td>
<td class="tiny"><strong><?php echo number_format($cfg["total_download"], 2); ?></strong> kB/s</td>
</tr>