diff --git a/app/Item.php b/app/Item.php index 0bc2299c..0067a9a8 100644 --- a/app/Item.php +++ b/app/Item.php @@ -57,6 +57,7 @@ class Item extends Model 'Sabnzbd' => \App\SupportedApps\Sabnzbd::class, 'Sickrage' => \App\SupportedApps\Sickrage::class, 'Sonarr' => \App\SupportedApps\Sonarr::class, + 'Transmission' => \App\SupportedApps\Transmission::class, 'Traefik' => \App\SupportedApps\Traefik::class, 'Ttrss' => \App\SupportedApps\Ttrss::class, 'UniFi' => \App\SupportedApps\Unifi::class, diff --git a/app/SupportedApps/Transmission.php b/app/SupportedApps/Transmission.php new file mode 100644 index 00000000..6dfd7077 --- /dev/null +++ b/app/SupportedApps/Transmission.php @@ -0,0 +1,166 @@ + ["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 = ' + + '; + 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; + } +} diff --git a/readme.md b/readme.md index 5b489b14..8b3a55d7 100644 --- a/readme.md +++ b/readme.md @@ -31,6 +31,7 @@ You can use the app to link to any site or application, but Foundation apps will - NZBGet - Pihole - Sabnzbd +- Transmission **Foundation** - Deluge diff --git a/resources/views/supportedapps/transmission.blade.php b/resources/views/supportedapps/transmission.blade.php new file mode 100644 index 00000000..be547b54 --- /dev/null +++ b/resources/views/supportedapps/transmission.blade.php @@ -0,0 +1,16 @@ +

{{ __('app.apps.config') }} ({{ __('app.optional') }})

+
+ + +
+ + {!! Form::text('config[username]', null, array('placeholder' => __('app.apps.username'), 'data-config' => 'username', 'class' => 'form-control config-item')) !!} +
+
+ + {!! Form::text('config[password]', null, array('placeholder' => __('app.apps.password'), 'data-config' => 'password', 'class' => 'form-control config-item')) !!} +
+
+ +
+
diff --git a/storage/app/public/supportedapps/transmission.png b/storage/app/public/supportedapps/transmission.png new file mode 100644 index 00000000..8b55fd4a Binary files /dev/null and b/storage/app/public/supportedapps/transmission.png differ diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 81f7a551..36785cf7 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -58,6 +58,7 @@ return array( 'App\\SupportedApps\\Sabnzbd' => $baseDir . '/app/SupportedApps/Sabnzbd.php', 'App\\SupportedApps\\Sonarr' => $baseDir . '/app/SupportedApps/Sonarr.php', 'App\\SupportedApps\\Traefik' => $baseDir . '/app/SupportedApps/Traefik.php', + 'App\\SupportedApps\\Transmission' => $baseDir . '/app/SupportedApps/Transmission.php', 'App\\SupportedApps\\Ttrss' => $baseDir . '/app/SupportedApps/Ttrss.php', 'App\\SupportedApps\\Unifi' => $baseDir . '/app/SupportedApps/Unifi.php', 'App\\SupportedApps\\ruTorrent' => $baseDir . '/app/SupportedApps/ruTorrent.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 98e17593..be408257 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -396,6 +396,7 @@ class ComposerStaticInit4b6fb9210a1ea37c2db27b8ff53a1ecf 'App\\SupportedApps\\Sabnzbd' => __DIR__ . '/../..' . '/app/SupportedApps/Sabnzbd.php', 'App\\SupportedApps\\Sonarr' => __DIR__ . '/../..' . '/app/SupportedApps/Sonarr.php', 'App\\SupportedApps\\Traefik' => __DIR__ . '/../..' . '/app/SupportedApps/Traefik.php', + 'App\\SupportedApps\\Transmission' => __DIR__ . '/../..' . '/app/SupportedApps/Transmission.php', 'App\\SupportedApps\\Ttrss' => __DIR__ . '/../..' . '/app/SupportedApps/Ttrss.php', 'App\\SupportedApps\\Unifi' => __DIR__ . '/../..' . '/app/SupportedApps/Unifi.php', 'App\\SupportedApps\\ruTorrent' => __DIR__ . '/../..' . '/app/SupportedApps/ruTorrent.php',