parent
ea74b96293
commit
958bef0dfa
@ -0,0 +1,48 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* Created by PhpStorm. |
||||||
|
* User: Rhilip |
||||||
|
* Date: 1/17/2020 |
||||||
|
* Time: 2020 |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace IYUU\Client\transmission; |
||||||
|
|
||||||
|
/** |
||||||
|
* This is the type of exception the TransmissionRPC class will throw |
||||||
|
*/ |
||||||
|
class TransmissionRPCException extends \Exception |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Exception: Invalid arguments |
||||||
|
*/ |
||||||
|
const E_INVALIDARG = -1; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception: Invalid Session-Id |
||||||
|
*/ |
||||||
|
const E_SESSIONID = -2; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception: Error while connecting |
||||||
|
*/ |
||||||
|
const E_CONNECTION = -3; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception: Error 401 returned, unauthorized |
||||||
|
*/ |
||||||
|
const E_AUTHENTICATION = -4; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception constructor |
||||||
|
*/ |
||||||
|
public function __construct($message = null, $code = 0, \Exception $previous = null) |
||||||
|
{ |
||||||
|
// PHP version 5.3.0 and above support Exception linking |
||||||
|
if (version_compare(PHP_VERSION, '5.3.0', '>=')) { |
||||||
|
parent::__construct($message, $code, $previous); |
||||||
|
} else { |
||||||
|
parent::__construct($message, $code); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,759 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* Transmission bittorrent client/daemon RPC communication class |
||||||
|
* Copyright (C) 2010 Johan Adriaans <johan.adriaans@gmail.com>, |
||||||
|
* Bryce Chidester <bryce@cobryce.com> |
||||||
|
* |
||||||
|
* This program is free software: you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation, either version 3 of the License, or |
||||||
|
* (at your option) any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* PHP version specific information |
||||||
|
* version_compare() (PHP 4 >= 4.1.0, PHP 5) |
||||||
|
* ctype_digit() (PHP 4 >= 4.0.4, PHP 5) |
||||||
|
* stream_context_create (PHP 4 >= 4.3.0, PHP 5) |
||||||
|
* PHP Class support (PHP 5) (PHP 4 might work, untested) |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace IYUU\Client\transmission; |
||||||
|
|
||||||
|
use IYUU\Client\AbstractClient; |
||||||
|
|
||||||
|
/** |
||||||
|
* A friendly little version check... |
||||||
|
*/ |
||||||
|
if (version_compare(PHP_VERSION, '5.2.10', '<')) { |
||||||
|
die("The TransmissionRPC class requires PHP version 5.2.10 or above." . PHP_EOL); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Transmission bittorrent client/daemon RPC communication class |
||||||
|
* |
||||||
|
* Usage example: |
||||||
|
* <code> |
||||||
|
* $rpc = new TransmissionRPC($rpc_url); |
||||||
|
* $result = $rpc->add_file( $url_or_path_to_torrent, $target_folder ); |
||||||
|
* </code> |
||||||
|
* |
||||||
|
*/ |
||||||
|
class transmission extends AbstractClient |
||||||
|
{ |
||||||
|
/** |
||||||
|
* User agent used in all http communication |
||||||
|
*/ |
||||||
|
const HTTP_UA = 'TransmissionRPC for PHP/0.3'; |
||||||
|
|
||||||
|
/** |
||||||
|
* The URL to the bittorent client you want to communicate with |
||||||
|
* the port (default: 9091) can be set in you Transmission preferences |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
public $url = ''; |
||||||
|
|
||||||
|
/** |
||||||
|
* If your Transmission RPC requires authentication, supply username here |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
public $username = ''; |
||||||
|
|
||||||
|
/** |
||||||
|
* If your Transmission RPC requires authentication, supply password here |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
public $password = ''; |
||||||
|
|
||||||
|
/** |
||||||
|
* Print debugging information, default is off |
||||||
|
* @var bool |
||||||
|
*/ |
||||||
|
public $debug = false; |
||||||
|
|
||||||
|
/** |
||||||
|
* Transmission RPC version |
||||||
|
* @var int |
||||||
|
*/ |
||||||
|
protected $rpc_version = 0; |
||||||
|
|
||||||
|
/** |
||||||
|
* Transmission uses a session id to prevent CSRF attacks |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
protected $session_id = ''; |
||||||
|
|
||||||
|
/** |
||||||
|
* Default values for stream context |
||||||
|
* @var array |
||||||
|
*/ |
||||||
|
private $default_context_opts = array( |
||||||
|
'http' => array( |
||||||
|
'user_agent' => self::HTTP_UA, |
||||||
|
'timeout' => '60', // Don't want to be too slow |
||||||
|
'ignore_errors' => true, // Leave the error parsing/handling to the code |
||||||
|
), |
||||||
|
"ssl"=>array( |
||||||
|
"verify_peer"=>false, |
||||||
|
"verify_peer_name"=>false, |
||||||
|
) |
||||||
|
); |
||||||
|
|
||||||
|
/** |
||||||
|
* Constants for torrent status |
||||||
|
*/ |
||||||
|
const TR_STATUS_STOPPED = 0; |
||||||
|
const TR_STATUS_CHECK_WAIT = 1; |
||||||
|
const TR_STATUS_CHECK = 2; |
||||||
|
const TR_STATUS_DOWNLOAD_WAIT = 3; |
||||||
|
const TR_STATUS_DOWNLOAD = 4; |
||||||
|
const TR_STATUS_SEED_WAIT = 5; |
||||||
|
const TR_STATUS_SEED = 6; |
||||||
|
|
||||||
|
const RPC_LT_14_TR_STATUS_CHECK_WAIT = 1; |
||||||
|
const RPC_LT_14_TR_STATUS_CHECK = 2; |
||||||
|
const RPC_LT_14_TR_STATUS_DOWNLOAD = 4; |
||||||
|
const RPC_LT_14_TR_STATUS_SEED = 8; |
||||||
|
const RPC_LT_14_TR_STATUS_STOPPED = 16; |
||||||
|
|
||||||
|
/** |
||||||
|
* Takes the connection parameters |
||||||
|
* |
||||||
|
* @param string $url |
||||||
|
* @param string $username |
||||||
|
* @param string $password |
||||||
|
*/ |
||||||
|
public function __construct($url = 'http://127.0.0.1:9091/transmission/rpc', $username = null, $password = null) |
||||||
|
{ |
||||||
|
$this->url = $url; |
||||||
|
$this->username = $username; |
||||||
|
$this->password = $password; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Start one or more torrents |
||||||
|
* |
||||||
|
* @param int|array ids A list of transmission torrent ids |
||||||
|
* @return mixed |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
public function start($ids) |
||||||
|
{ |
||||||
|
if (!is_array($ids)) { |
||||||
|
$ids = array($ids); |
||||||
|
} |
||||||
|
$request = array("ids" => $ids); |
||||||
|
return $this->request("torrent-start", $request); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Stop one or more torrents |
||||||
|
* |
||||||
|
* @param int|array ids A list of transmission torrent ids |
||||||
|
* @return mixed |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
public function stop($ids) |
||||||
|
{ |
||||||
|
if (!is_array($ids)) { |
||||||
|
$ids = array($ids); |
||||||
|
} |
||||||
|
$request = array("ids" => $ids); |
||||||
|
return $this->request("torrent-stop", $request); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Reannounce one or more torrents |
||||||
|
* |
||||||
|
* @param int|array ids A list of transmission torrent ids |
||||||
|
* @return mixed |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
public function reannounce($ids) |
||||||
|
{ |
||||||
|
if (!is_array($ids)) { |
||||||
|
$ids = array($ids); |
||||||
|
} |
||||||
|
$request = array("ids" => $ids); |
||||||
|
return $this->request("torrent-reannounce", $request); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Verify one or more torrents |
||||||
|
* |
||||||
|
* @param int|array ids A list of transmission torrent ids |
||||||
|
* @return mixed |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
public function verify($ids) |
||||||
|
{ |
||||||
|
if (!is_array($ids)) { |
||||||
|
$ids = array($ids); |
||||||
|
} |
||||||
|
$request = array("ids" => $ids); |
||||||
|
return $this->request("torrent-verify", $request); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get information on torrents in transmission, if the ids parameter is |
||||||
|
* empty all torrents will be returned. The fields array can be used to return certain |
||||||
|
* fields. Default fields are: "id", "name", "status", "doneDate", "haveValid", "totalSize". |
||||||
|
* See https://github.com/transmission/transmission/blob/2.9x/extras/rpc-spec.txt for available fields |
||||||
|
* |
||||||
|
* @param array fields An array of return fields |
||||||
|
* @param int|array ids A list of transmission torrent ids |
||||||
|
* |
||||||
|
* Request: |
||||||
|
* { |
||||||
|
* "arguments": { |
||||||
|
* "fields": [ "id", "name", "totalSize" ], |
||||||
|
* "ids": [ 7, 10 ] |
||||||
|
* }, |
||||||
|
* "method": "torrent-get", |
||||||
|
* "tag": 39693 |
||||||
|
* } |
||||||
|
* |
||||||
|
* Response: |
||||||
|
* { |
||||||
|
* "arguments": { |
||||||
|
* "torrents": [ |
||||||
|
* { |
||||||
|
* "id": 10, |
||||||
|
* "name": "Fedora x86_64 DVD", |
||||||
|
* "totalSize": 34983493932, |
||||||
|
* }, |
||||||
|
* { |
||||||
|
* "id": 7, |
||||||
|
* "name": "Ubuntu x86_64 DVD", |
||||||
|
* "totalSize", 9923890123, |
||||||
|
* } |
||||||
|
* ] |
||||||
|
* }, |
||||||
|
* "result": "success", |
||||||
|
* "tag": 39693 |
||||||
|
* } |
||||||
|
* @return mixed |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
public function get($ids = array(), $fields = array()) |
||||||
|
{ |
||||||
|
if (!is_array($ids)) { |
||||||
|
$ids = array($ids); |
||||||
|
} // Convert $ids to an array if only a single id was passed |
||||||
|
if (count($fields) == 0) { |
||||||
|
$fields = array("id", "name", "status", "doneDate", "haveValid", "totalSize"); |
||||||
|
} // Defaults |
||||||
|
$request = array( |
||||||
|
"fields" => $fields, |
||||||
|
"ids" => $ids |
||||||
|
); |
||||||
|
return $this->request("torrent-get", $request); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set properties on one or more torrents, available fields are: |
||||||
|
* "bandwidthPriority" | number this torrent's bandwidth tr_priority_t |
||||||
|
* "downloadLimit" | number maximum download speed (in K/s) |
||||||
|
* "downloadLimited" | boolean true if "downloadLimit" is honored |
||||||
|
* "files-wanted" | array indices of file(s) to download |
||||||
|
* "files-unwanted" | array indices of file(s) to not download |
||||||
|
* "honorsSessionLimits" | boolean true if session upload limits are honored |
||||||
|
* "ids" | array torrent list, as described in 3.1 |
||||||
|
* "location" | string new location of the torrent's content |
||||||
|
* "peer-limit" | number maximum number of peers |
||||||
|
* "priority-high" | array indices of high-priority file(s) |
||||||
|
* "priority-low" | array indices of low-priority file(s) |
||||||
|
* "priority-normal" | array indices of normal-priority file(s) |
||||||
|
* "seedRatioLimit" | double session seeding ratio |
||||||
|
* "seedRatioMode" | number which ratio to use. See tr_ratiolimit |
||||||
|
* "uploadLimit" | number maximum upload speed (in K/s) |
||||||
|
* "uploadLimited" | boolean true if "uploadLimit" is honored |
||||||
|
* See https://github.com/transmission/transmission/blob/2.9x/extras/rpc-spec.txt for more information |
||||||
|
* |
||||||
|
* @param array arguments An associative array of arguments to set |
||||||
|
* @param int|array ids A list of transmission torrent ids |
||||||
|
* @return mixed |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
public function set($ids = array(), $arguments = array()) |
||||||
|
{ |
||||||
|
// See https://github.com/transmission/transmission/blob/2.9x/extras/rpc-spec.txt for available fields |
||||||
|
if (!is_array($ids)) { |
||||||
|
$ids = array($ids); |
||||||
|
} // Convert $ids to an array if only a single id was passed |
||||||
|
if (!isset($arguments['ids'])) { |
||||||
|
$arguments['ids'] = $ids; |
||||||
|
} // Any $ids given in $arguments overrides the method parameter |
||||||
|
return $this->request("torrent-set", $arguments); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add a new torrent |
||||||
|
* |
||||||
|
* Available extra options: |
||||||
|
* key | value type & description |
||||||
|
* ---------------------+------------------------------------------------- |
||||||
|
* "download-dir" | string path to download the torrent to |
||||||
|
* "filename" | string filename or URL of the .torrent file |
||||||
|
* "metainfo" | string base64-encoded .torrent content |
||||||
|
* "paused" | boolean if true, don't start the torrent |
||||||
|
* "peer-limit" | number maximum number of peers |
||||||
|
* "bandwidthPriority" | number torrent's bandwidth tr_priority_t |
||||||
|
* "files-wanted" | array indices of file(s) to download |
||||||
|
* "files-unwanted" | array indices of file(s) to not download |
||||||
|
* "priority-high" | array indices of high-priority file(s) |
||||||
|
* "priority-low" | array indices of low-priority file(s) |
||||||
|
* "priority-normal" | array indices of normal-priority file(s) |
||||||
|
* |
||||||
|
* Either "filename" OR "metainfo" MUST be included. |
||||||
|
* All other arguments are optional. |
||||||
|
* |
||||||
|
* @param string $torrent_location The URL or path to the torrent file |
||||||
|
* @param string $save_path Folder to save torrent in |
||||||
|
* @param array $extra_options Optional extra torrent options |
||||||
|
* @return mixed |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
public function add_file($torrent_location, $save_path = '', $extra_options = array()) |
||||||
|
{ |
||||||
|
if (!empty($save_path)) { |
||||||
|
$extra_options['download-dir'] = $save_path; |
||||||
|
} |
||||||
|
$extra_options['filename'] = $torrent_location; |
||||||
|
|
||||||
|
return $this->request("torrent-add", $extra_options); |
||||||
|
} |
||||||
|
|
||||||
|
/* Add a new torrent using a file path or a URL (For backwards compatibility) |
||||||
|
* @param torrent_location The URL or path to the torrent file |
||||||
|
* @param save_path Folder to save torrent in |
||||||
|
* @param extra options Optional extra torrent options |
||||||
|
*/ |
||||||
|
public function add($torrent_location, $save_path = '', $extra_options = array()) |
||||||
|
{ |
||||||
|
return $this->add_file($torrent_location, $save_path, $extra_options); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add a torrent using the raw torrent data |
||||||
|
* |
||||||
|
* @param string $torrent_metainfo The raw, unencoded contents (metainfo) of a torrent |
||||||
|
* @param string $save_path Folder to save torrent in |
||||||
|
* @param array $extra_options Optional extra torrent options |
||||||
|
* @return mixed |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
public function add_metainfo($torrent_metainfo, $save_path = '', $extra_options = array()) |
||||||
|
{ |
||||||
|
if (!empty($save_path)) { |
||||||
|
$extra_options['download-dir'] = $save_path; |
||||||
|
} |
||||||
|
$extra_options['metainfo'] = base64_encode($torrent_metainfo); |
||||||
|
|
||||||
|
return $this->request("torrent-add", $extra_options); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Remove torrent from transmission |
||||||
|
* |
||||||
|
* @param bool delete_local_data Also remove local data? |
||||||
|
* @param int|array ids A list of transmission torrent ids |
||||||
|
* @return mixed |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
public function delete($ids, $delete_local_data = false) |
||||||
|
{ |
||||||
|
if (!is_array($ids)) { |
||||||
|
$ids = array($ids); |
||||||
|
} // Convert $ids to an array if only a single id was passed |
||||||
|
$request = array( |
||||||
|
"ids" => $ids, |
||||||
|
"delete-local-data" => $delete_local_data |
||||||
|
); |
||||||
|
return $this->request("torrent-remove", $request); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Move local storage location |
||||||
|
* |
||||||
|
* @param int|array ids A list of transmission torrent ids |
||||||
|
* @param string target_location The new storage location |
||||||
|
* @param string move_existing_data Move existing data or scan new location for available data |
||||||
|
* @return mixed |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
public function move($ids, $target_location, $move_existing_data = true) |
||||||
|
{ |
||||||
|
if (!is_array($ids)) { |
||||||
|
$ids = array($ids); |
||||||
|
} // Convert $ids to an array if only a single id was passed |
||||||
|
$request = array( |
||||||
|
"ids" => $ids, |
||||||
|
"location" => $target_location, |
||||||
|
"move" => $move_existing_data |
||||||
|
); |
||||||
|
return $this->request("torrent-set-location", $request); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 3.7. Renaming a Torrent's Path |
||||||
|
* |
||||||
|
* Method name: "torrent-rename-path" |
||||||
|
* |
||||||
|
* For more information on the use of this function, see the transmission.h |
||||||
|
* documentation of tr_torrentRenamePath(). In particular, note that if this |
||||||
|
* call succeeds you'll want to update the torrent's "files" and "name" field |
||||||
|
* with torrent-get. |
||||||
|
* |
||||||
|
* Request arguments: |
||||||
|
* |
||||||
|
* string | value type & description |
||||||
|
* ---------------------------------+------------------------------------------------- |
||||||
|
* "ids" | array the torrent torrent list, as described in 3.1 |
||||||
|
* | (must only be 1 torrent) |
||||||
|
* "path" | string the path to the file or folder that will be renamed |
||||||
|
* "name" | string the file or folder's new name |
||||||
|
* Response arguments: "path", "name", and "id", holding the torrent ID integer |
||||||
|
* |
||||||
|
* @param int|array ids A 1-element list of transmission torrent ids |
||||||
|
* @param string path The path to the file or folder that will be renamed |
||||||
|
* @param string name The file or folder's new name |
||||||
|
* @return mixed |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
public function rename($ids, $path, $name) |
||||||
|
{ |
||||||
|
if (!is_array($ids)) { |
||||||
|
$ids = array($ids); |
||||||
|
} // Convert $id to an array if only a single id was passed |
||||||
|
if (count($ids) !== 1) { |
||||||
|
throw new TransmissionRPCException('A single id is accepted', TransmissionRPCException::E_INVALIDARG); |
||||||
|
} |
||||||
|
|
||||||
|
$request = array( |
||||||
|
"ids" => $ids, |
||||||
|
"path" => $path, |
||||||
|
"name" => $name |
||||||
|
); |
||||||
|
return $this->request("torrent-rename-path", $request); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Retrieve session statistics |
||||||
|
* |
||||||
|
* @returns array of statistics |
||||||
|
*/ |
||||||
|
public function sstats() |
||||||
|
{ |
||||||
|
return $this->request("session-stats", array()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Retrieve all session variables |
||||||
|
* |
||||||
|
* @returns array of session information |
||||||
|
*/ |
||||||
|
public function sget() |
||||||
|
{ |
||||||
|
return $this->request("session-get", array()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set session variable(s) |
||||||
|
* |
||||||
|
* @param array of session variables to set |
||||||
|
* @return mixed |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
public function sset($arguments) |
||||||
|
{ |
||||||
|
return $this->request("session-set", $arguments); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the interpretation of the torrent status |
||||||
|
* |
||||||
|
* @param int The integer "torrent status" |
||||||
|
* @returns string The translated meaning |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public function getStatusString($intstatus) |
||||||
|
{ |
||||||
|
if ($this->rpc_version < 14) { |
||||||
|
if ($intstatus == self::RPC_LT_14_TR_STATUS_CHECK_WAIT) { |
||||||
|
return "Waiting to verify local files"; |
||||||
|
} |
||||||
|
if ($intstatus == self::RPC_LT_14_TR_STATUS_CHECK) { |
||||||
|
return "Verifying local files"; |
||||||
|
} |
||||||
|
if ($intstatus == self::RPC_LT_14_TR_STATUS_DOWNLOAD) { |
||||||
|
return "Downloading"; |
||||||
|
} |
||||||
|
if ($intstatus == self::RPC_LT_14_TR_STATUS_SEED) { |
||||||
|
return "Seeding"; |
||||||
|
} |
||||||
|
if ($intstatus == self::RPC_LT_14_TR_STATUS_STOPPED) { |
||||||
|
return "Stopped"; |
||||||
|
} |
||||||
|
} else { |
||||||
|
if ($intstatus == self::TR_STATUS_CHECK_WAIT) { |
||||||
|
return "Waiting to verify local files"; |
||||||
|
} |
||||||
|
if ($intstatus == self::TR_STATUS_CHECK) { |
||||||
|
return "Verifying local files"; |
||||||
|
} |
||||||
|
if ($intstatus == self::TR_STATUS_DOWNLOAD) { |
||||||
|
return "Downloading"; |
||||||
|
} |
||||||
|
if ($intstatus == self::TR_STATUS_SEED) { |
||||||
|
return "Seeding"; |
||||||
|
} |
||||||
|
if ($intstatus == self::TR_STATUS_STOPPED) { |
||||||
|
return "Stopped"; |
||||||
|
} |
||||||
|
if ($intstatus == self::TR_STATUS_SEED_WAIT) { |
||||||
|
return "Queued for seeding"; |
||||||
|
} |
||||||
|
if ($intstatus == self::TR_STATUS_DOWNLOAD_WAIT) { |
||||||
|
return "Queued for download"; |
||||||
|
} |
||||||
|
} |
||||||
|
return "Unknown"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Here be dragons (Internal methods) |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Clean up the request array. Removes any empty fields from the request |
||||||
|
* |
||||||
|
* @param array array The request associative array to clean |
||||||
|
* @returns array The cleaned array |
||||||
|
* @return array|null |
||||||
|
*/ |
||||||
|
protected function cleanRequestData($array) |
||||||
|
{ |
||||||
|
if (!is_array($array) || count($array) == 0) { |
||||||
|
return null; |
||||||
|
} // Nothing to clean |
||||||
|
setlocale(LC_NUMERIC, 'en_US.utf8'); // Override the locale - if the system locale is wrong, then 12.34 will encode as 12,34 which is invalid JSON |
||||||
|
foreach ($array as $index => $value) { |
||||||
|
if (is_object($value)) { |
||||||
|
$array[$index] = $value->toArray(); |
||||||
|
} // Convert objects to arrays so they can be JSON encoded |
||||||
|
if (is_array($value)) { |
||||||
|
$array[$index] = $this->cleanRequestData($value); |
||||||
|
} // Recursion |
||||||
|
if (empty($value) && $value !== 0) { // Remove empty members |
||||||
|
unset($array[$index]); |
||||||
|
continue; // Skip the rest of the tests - they may re-add the element. |
||||||
|
} |
||||||
|
if (is_numeric($value)) { |
||||||
|
$array[$index] = $value + 0; |
||||||
|
} // Force type-casting for proper JSON encoding (+0 is a cheap way to maintain int/float/etc) |
||||||
|
if (is_bool($value)) { |
||||||
|
$array[$index] = ($value ? 1 : 0); |
||||||
|
} // Store boolean values as 0 or 1 |
||||||
|
if (is_string($value)) { |
||||||
|
$type = mb_detect_encoding($value, "auto"); |
||||||
|
if ($type !== 'UTF-8') { |
||||||
|
$array[$index] = mb_convert_encoding($value, "UTF-8"); |
||||||
|
//utf8_encode( $value ); // Make sure all data is UTF-8 encoded for Transmission |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return $array; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 执行 rpc 请求 |
||||||
|
* |
||||||
|
* @param string $method 请求类型/方法, 详见 $this->allowMethods |
||||||
|
* @param array $arguments 附加参数, 可选 |
||||||
|
* @return array |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
protected function request($method, $arguments = array()) |
||||||
|
{ |
||||||
|
// Check the parameters |
||||||
|
if (!is_scalar($method)) { |
||||||
|
throw new TransmissionRPCException('Method name has no scalar value', TransmissionRPCException::E_INVALIDARG); |
||||||
|
} |
||||||
|
if (!is_array($arguments)) { |
||||||
|
throw new TransmissionRPCException('Arguments must be given as array', TransmissionRPCException::E_INVALIDARG); |
||||||
|
} |
||||||
|
|
||||||
|
$arguments = $this->cleanRequestData($arguments); // Sanitize input |
||||||
|
|
||||||
|
// Grab the X-Transmission-Session-Id if we don't have it already |
||||||
|
if (!$this->session_id) { |
||||||
|
if (!$this->GetSessionID()) { |
||||||
|
throw new TransmissionRPCException('Unable to acquire X-Transmission-Session-Id', TransmissionRPCException::E_SESSIONID); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$data = array( |
||||||
|
'method' => $method, |
||||||
|
'arguments' => $arguments |
||||||
|
); |
||||||
|
|
||||||
|
$header = array( |
||||||
|
'Content-Type: application/json', |
||||||
|
'Authorization: Basic ' . base64_encode(sprintf("%s:%s", $this->username, $this->password)), |
||||||
|
'X-Transmission-Session-Id: ' . $this->session_id |
||||||
|
); |
||||||
|
|
||||||
|
$ch = curl_init(); |
||||||
|
curl_setopt($ch, CURLOPT_URL, $this->url); |
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); |
||||||
|
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); |
||||||
|
curl_setopt($ch, CURLOPT_USERPWD, $this->username . ':' . $this->password); |
||||||
|
curl_setopt($ch, CURLOPT_HEADER, false); |
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||||||
|
curl_setopt($ch, CURLOPT_POST, true); |
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); |
||||||
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); |
||||||
|
curl_setopt($ch, CURLOPT_TIMEOUT, 600); |
||||||
|
$content = curl_exec($ch); |
||||||
|
curl_close($ch); |
||||||
|
|
||||||
|
if (!$content) { |
||||||
|
$content = array('result' => 'failed'); |
||||||
|
} |
||||||
|
return json_decode($content, true); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Performs an empty GET on the Transmission RPC to get the X-Transmission-Session-Id |
||||||
|
* and store it in $this->session_id |
||||||
|
* |
||||||
|
* @return string |
||||||
|
* @throws TransmissionRPCException |
||||||
|
*/ |
||||||
|
public function GetSessionID() |
||||||
|
{ |
||||||
|
if (!$this->url) { |
||||||
|
throw new TransmissionRPCException("Class must be initialized before GetSessionID() can be called.", TransmissionRPCException::E_INVALIDARG); |
||||||
|
} |
||||||
|
|
||||||
|
// Setup the context |
||||||
|
$contextopts = $this->default_context_opts; // Start with the defaults |
||||||
|
|
||||||
|
// Make sure it's blank/empty (reset) |
||||||
|
$this->session_id = null; |
||||||
|
|
||||||
|
// Setup authentication (if provided) |
||||||
|
if ($this->username && $this->password) { |
||||||
|
$contextopts['http']['header'] = sprintf("Authorization: Basic %s\r\n", base64_encode($this->username . ':' . $this->password)); |
||||||
|
} |
||||||
|
|
||||||
|
if ($this->debug) { |
||||||
|
echo "TRANSMISSIONRPC_DEBUG:: GetSessionID():: Stream context created with options:" . |
||||||
|
PHP_EOL . print_r($contextopts, true); |
||||||
|
} |
||||||
|
|
||||||
|
$context = stream_context_create($contextopts); // Create the context for this request |
||||||
|
if (!$fp = @fopen($this->url, 'r', false, $context)) { // Open a filepointer to the data, and use fgets to get the result |
||||||
|
throw new TransmissionRPCException('Unable to connect to ' . $this->url, TransmissionRPCException::E_CONNECTION); |
||||||
|
} |
||||||
|
|
||||||
|
// Check the response (headers etc) |
||||||
|
$stream_meta = stream_get_meta_data($fp); |
||||||
|
fclose($fp); |
||||||
|
if ($this->debug) { |
||||||
|
echo "TRANSMISSIONRPC_DEBUG:: GetSessionID():: Stream meta info: " . |
||||||
|
PHP_EOL . print_r($stream_meta, true); |
||||||
|
} |
||||||
|
if ($stream_meta['timed_out']) { |
||||||
|
throw new TransmissionRPCException("Timed out connecting to {$this->url}", TransmissionRPCException::E_CONNECTION); |
||||||
|
} |
||||||
|
if (substr($stream_meta['wrapper_data'][0], 9, 3) == "401") { |
||||||
|
throw new TransmissionRPCException("Invalid username/password.", TransmissionRPCException::E_AUTHENTICATION); |
||||||
|
} elseif (substr($stream_meta['wrapper_data'][0], 9, 3) == "409") { // This is what we're hoping to find |
||||||
|
// Loop through the returned headers and extract the X-Transmission-Session-Id |
||||||
|
foreach ($stream_meta['wrapper_data'] as $header) { |
||||||
|
if (strpos($header, 'X-Transmission-Session-Id: ') === 0) { |
||||||
|
if ($this->debug) { |
||||||
|
echo "TRANSMISSIONRPC_DEBUG:: GetSessionID():: Session-Id header: " . |
||||||
|
PHP_EOL . print_r($header, true); |
||||||
|
} |
||||||
|
$this->session_id = trim(substr($header, 27)); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (!$this->session_id) { // Didn't find a session_id |
||||||
|
throw new TransmissionRPCException("Unable to retrieve X-Transmission-Session-Id", TransmissionRPCException::E_SESSIONID); |
||||||
|
} |
||||||
|
} else { |
||||||
|
throw new TransmissionRPCException("Unexpected response from Transmission RPC: " . $stream_meta['wrapper_data'][0]); |
||||||
|
} |
||||||
|
return $this->session_id; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 抽象方法,子类实现 |
||||||
|
*/ |
||||||
|
public function status() |
||||||
|
{ |
||||||
|
$rs = $this->sstats(); |
||||||
|
return isset($rs['result']) ? $rs['result'] : 'error'; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 抽象方法,子类实现 |
||||||
|
*/ |
||||||
|
public function getList(&$move = array()) |
||||||
|
{ |
||||||
|
$ids = array(); |
||||||
|
$fields = array( "id", "status", "name", "hashString", "downloadDir", "torrentFile" ); |
||||||
|
$res = $this->get($ids, $fields); |
||||||
|
if (isset($res['result']) && $res['result'] == 'success') { |
||||||
|
// 成功 |
||||||
|
} else { |
||||||
|
// 失败 |
||||||
|
echo "获取种子列表失败,可能transmission暂时无响应,请稍后重试!".PHP_EOL; |
||||||
|
return array(); |
||||||
|
} |
||||||
|
if (empty($res['arguments']['torrents'])) { |
||||||
|
echo "未获取到正常做种数据,请多保种,然后重试!".PHP_EOL; |
||||||
|
return array(); |
||||||
|
} |
||||||
|
$res = $res['arguments']['torrents']; |
||||||
|
// 过滤,只保留正常做种 |
||||||
|
$res = array_filter($res, function ($v) { |
||||||
|
return isset($v['status']) && $v['status']===6; |
||||||
|
}, ARRAY_FILTER_USE_BOTH); |
||||||
|
|
||||||
|
if (empty($res)) { |
||||||
|
echo "未获取到正常做种数据,请多保种,然后重试!".PHP_EOL; |
||||||
|
return array(); |
||||||
|
} |
||||||
|
// 提取数组:hashString |
||||||
|
$info_hash = array_column($res, 'hashString'); |
||||||
|
// 升序排序 |
||||||
|
sort($info_hash); |
||||||
|
$json = json_encode($info_hash, JSON_UNESCAPED_UNICODE); |
||||||
|
// 去重 应该从文件读入,防止重复提交 |
||||||
|
$sha1 = sha1($json); |
||||||
|
// 组装返回数据 |
||||||
|
$hashArray['hash'] = $json; |
||||||
|
$hashArray['sha1'] = $sha1; |
||||||
|
// 变换数组:hashString为键 |
||||||
|
$hashArray['hashString'] = array_column($res, "downloadDir", 'hashString'); |
||||||
|
$move = array_column($res, null, 'hashString'); |
||||||
|
return $hashArray; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue