John Alberts
7 years ago
9 changed files with 189 additions and 0 deletions
@ -0,0 +1,167 @@ |
|||||
|
<?php namespace App\SupportedApps; |
||||
|
|
||||
|
use GuzzleHttp\Exception\GuzzleException; |
||||
|
use GuzzleHttp\Client; |
||||
|
use Illuminate\Support\Facades\Log; |
||||
|
|
||||
|
class Transmission implements Contracts\Applications, Contracts\Livestats |
||||
|
{ |
||||
|
|
||||
|
private $_client; |
||||
|
private $_clientOptions = array(); |
||||
|
|
||||
|
public function __construct() |
||||
|
{ |
||||
|
$body = array(); |
||||
|
$body["method"] = "torrent-get"; |
||||
|
$body["arguments"] = array("fields" => ["percentDone","status","rateDownload","rateUpload"]); |
||||
|
$this->_client = new Client( |
||||
|
['http_errors' => false, |
||||
|
'timeout' => 10, |
||||
|
'body' => json_encode($body)] |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public function defaultColour() |
||||
|
{ |
||||
|
return '#950003'; |
||||
|
} |
||||
|
public function icon() |
||||
|
{ |
||||
|
return 'supportedapps/Transmission.png'; |
||||
|
} |
||||
|
public function configDetails() |
||||
|
{ |
||||
|
return 'transmission'; |
||||
|
} |
||||
|
public function testConfig() |
||||
|
{ |
||||
|
$res = $this->sendRequest(); |
||||
|
if ($res == null) { |
||||
|
echo 'Transmission connection failed'; |
||||
|
return; |
||||
|
} |
||||
|
switch($res->getStatusCode()) { |
||||
|
case 200: |
||||
|
$data = json_decode($res->getBody()); |
||||
|
echo "Successfully connected with status: ".$data->result."\n"; |
||||
|
break; |
||||
|
case 401: |
||||
|
echo 'Failed: Invalid credentials'; |
||||
|
break; |
||||
|
case 404: |
||||
|
echo 'Failed: Please make sure your URL is correct and includes the port'; |
||||
|
break; |
||||
|
case 409: |
||||
|
echo 'Failed: Incorrect session id'; |
||||
|
break; |
||||
|
default: |
||||
|
echo 'Something went wrong... Code: '.$res->getStatusCode(); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public function executeConfig() |
||||
|
{ |
||||
|
$html = ''; |
||||
|
$active = 'active'; |
||||
|
$res = $this->sendRequest(); |
||||
|
if ($res == null) { |
||||
|
Log::debug('Transmission connection failed'); |
||||
|
return ''; |
||||
|
} |
||||
|
$data = json_decode($res->getBody()); |
||||
|
if (! isset($data->arguments)) { |
||||
|
Log::debug('Failed to fetch data from Transmission'); |
||||
|
return ''; |
||||
|
} |
||||
|
$torrents = $data->arguments->torrents; |
||||
|
$torrentCount = count($torrents); |
||||
|
$rateDownload = $rateUpload = $completedTorrents = 0; |
||||
|
foreach ($torrents as $thisTorrent) { |
||||
|
$rateDownload += $thisTorrent->rateDownload; |
||||
|
$rateUpload += $thisTorrent->rateUpload; |
||||
|
if ($thisTorrent->percentDone == 1) { |
||||
|
$completedTorrents += 1; |
||||
|
} |
||||
|
} |
||||
|
if ($torrentCount - $completedTorrents == 0) { |
||||
|
// Don't poll as frequently if we don't have any active torrents |
||||
|
$active = 'inactive'; |
||||
|
} |
||||
|
|
||||
|
$html = ' |
||||
|
<ul class="livestats"> |
||||
|
<li><span class="title">Done</span><sub>'.$completedTorrents.' / '.$torrentCount.'</sub></li> |
||||
|
<li><span class="title">Down</span><sub>'.format_bytes($rateDownload).'</sub></li> |
||||
|
<li><span class="title">Up</span><sub>'.format_bytes($rateUpload).'</sub></li> |
||||
|
</ul> |
||||
|
'; |
||||
|
return json_encode(['status' => $active, 'html' => $html]);; |
||||
|
} |
||||
|
|
||||
|
private function sendRequest() |
||||
|
{ |
||||
|
$optionsSet = $this->setClientOptions(); |
||||
|
if (! $optionsSet) { |
||||
|
// Pass the failed response back up the chain |
||||
|
return null; |
||||
|
} |
||||
|
$res = $this->torrentGet(); |
||||
|
if ($res->getStatusCode() == 409) { |
||||
|
$this->setClientOptions(); |
||||
|
$res = $this->torrentGet(); |
||||
|
} |
||||
|
return $res; |
||||
|
} |
||||
|
|
||||
|
private function torrentGet() |
||||
|
{ |
||||
|
$res = null; |
||||
|
try{ |
||||
|
$res = $this->_client->request( |
||||
|
'POST', |
||||
|
$this->getApiUrl(), |
||||
|
$this->_clientOptions |
||||
|
); |
||||
|
}catch(\GuzzleHttp\Exception\BadResponseException $e){ |
||||
|
Log::error("Connection to {$e->getRequest()->getUrl()} failed"); |
||||
|
Log::debug($e->getMessage()); |
||||
|
$res = $e->getRequest(); |
||||
|
}catch(\GuzzleHttp\Exception\ConnectException $e) { |
||||
|
Log::error("Transmission connection refused"); |
||||
|
Log::debug($e->getMessage()); |
||||
|
} |
||||
|
|
||||
|
return $res; |
||||
|
} |
||||
|
|
||||
|
private function setClientOptions() |
||||
|
{ |
||||
|
if ($this->config->username != '' || $this->config->password != '') { |
||||
|
$this->_clientOptions = ['auth'=> [$this->config->username, $this->config->password, 'Basic']]; |
||||
|
} |
||||
|
try{ |
||||
|
$res = $this->_client->request('HEAD', $this->getApiUrl(), $this->_clientOptions); |
||||
|
$xtId = $res->getHeaderLine('X-Transmission-Session-Id'); |
||||
|
if ($xtId != null) { |
||||
|
$this->_clientOptions['headers'] = ['X-Transmission-Session-Id' => $xtId]; |
||||
|
} else { |
||||
|
Log::error("Unable to get Transmission session information"); |
||||
|
Log::debug("Status Code: ".$res->getStatusCode()); |
||||
|
} |
||||
|
}catch(\GuzzleHttp\Exception\ConnectException $e){ |
||||
|
Log::error("Failed connection to Transmission"); |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
private function getApiUrl() |
||||
|
{ |
||||
|
$url = $this->config->url; |
||||
|
$url = rtrim($url, '/'); |
||||
|
$apiUrl = $url.'/transmission/rpc'; |
||||
|
return $apiUrl; |
||||
|
} |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
<h2>{{ __('app.apps.config') }} ({{ __('app.optional') }})</h2> |
||||
|
<div class="items"> |
||||
|
<input type="hidden" name="config[enabled]" value="1" /> |
||||
|
<input type="hidden" data-config="type" class="config-item" name="config[type]" value="\App\SupportedApps\Transmission" /> |
||||
|
<div class="input"> |
||||
|
<label>{{ __('app.apps.username') }}</label> |
||||
|
{!! Form::text('config[username]', null, array('placeholder' => __('app.apps.username'), 'data-config' => 'username', 'class' => 'form-control config-item')) !!} |
||||
|
</div> |
||||
|
<div class="input"> |
||||
|
<label>{{ __('app.apps.password') }}</label> |
||||
|
{!! Form::text('config[password]', null, array('placeholder' => __('app.apps.password'), 'data-config' => 'password', 'class' => 'form-control config-item')) !!} |
||||
|
</div> |
||||
|
<div class="input"> |
||||
|
<button style="margin-top: 32px;" class="btn test" id="test_config">Test</button> |
||||
|
</div> |
||||
|
</div> |
@ -0,0 +1 @@ |
|||||
|
/config/www/backgrounds |
@ -0,0 +1 @@ |
|||||
|
/config/www/icons |
After Width: | Height: | Size: 38 KiB |
Loading…
Reference in new issue