RPC和AutoReseed文件重复

master
Rhilip 5 years ago
parent 27104bd9a2
commit b0607dbcf0
  1. 11
      app/AutoReseed.php
  2. 367
      app/Client/Rpc.php
  3. 351
      app/Client/Transmission/TransmissionRPC.php
  4. 2
      app/Client/Transmission/TransmissionRPCException.php
  5. 2
      composer.json
  6. 2
      init.php

@ -5,6 +5,8 @@
namespace IYUU;
use Curl\Curl;
use IYUU\Client\qBittorrent\qBittorrent;
use IYUU\Client\Transmission\TransmissionRPC;
use IYUU\Library\IFile;
use IYUU\Library\Oauth;
@ -94,6 +96,7 @@ class AutoReseed
// 合作站点自动注册鉴权
Oauth::login(self::$apiUrl . self::$endpoints['login']);
}
/**
* 连接远端RPC服务器
*
@ -132,7 +135,7 @@ class AutoReseed
if (isset($v['move']) && $v['move']) {
self::$move = array($k,$v['type']);
}
} catch (Exception $e) {
} catch (\Exception $e) {
echo '[ERROR] ' . $e->getMessage() . PHP_EOL;
exit(1);
}
@ -228,7 +231,7 @@ class AutoReseed
if (self::$move != null && (empty($v['move']))) {
self::move($res, $v['type']);
}
} catch (Exception $e) {
} catch (\Exception $e) {
echo '[ERROR] ' . $e->getMessage() . PHP_EOL;
exit(1);
}
@ -303,7 +306,7 @@ class AutoReseed
echo '[ERROR] '.$type;
break;
}
} catch (Exception $e) {
} catch (\Exception $e) {
echo '[ERROR] ' . $e->getMessage() . PHP_EOL;
}
return false;
@ -329,6 +332,7 @@ class AutoReseed
break;
}
}
/**
* @brief 提交种子hash给远端API,用来获取辅种数据
* @param array $hashArray 种子hash数组
@ -569,6 +573,7 @@ class AutoReseed
}
// 按客户端循环辅种 结束
}
/**
*
*/

@ -1,367 +0,0 @@
<?php
/**
* Rpc操作类
*/
class Rpc
{
/**
* 版本号
* @var string
*/
const VER = '0.0.1';
// 下载种子的请求类型 GET POST
public static $method = 'GET';
// RPC连接池
public static $links = array();
/**
* cookie
*/
public static $cookies = '';
/**
* 浏览器 User-Agent
*/
public static $userAgent = '';
/**
* passkey
*/
public static $passkey = '';
/**
* 客户端配置
*/
public static $clients = '';
/**
* 监控目录
*/
public static $watch = '';
/**
* 种子存放路径
*/
public static $torrentDir = '';
/**
* 工作模式
*/
public static $workingMode = '';
// 站点标识
public static $site = '';
/**
* 负载均衡 控制变量
*/
public static $RPC_Key = 0;
/**
* 退出状态码
*/
public static $ExitCode = 0;
/**
* 初始化
*/
public static function init($site = '', $method = 'GET')
{
global $configALL;
self::$site = $site;
self::$method = strtoupper($method);
$config = $configALL[$site];
self::$cookies = $config['cookie'];
self::$userAgent = isset($config['userAgent']) && $config['userAgent'] ? $config['userAgent'] : $configALL['default']['userAgent'];
self::$clients = isset($config['clients']) && $config['clients'] ? $config['clients'] : $configALL['default']['clients'];
self::$workingMode = isset($config['workingMode']) && $config['workingMode'] ? $config['workingMode'] : 0;
$watch = isset($config['watch']) && $config['watch'] ? $config['watch'] : $configALL['default']['watch'];
self::$watch = rtrim($watch, '/') . DS;
self::$torrentDir = TORRENT_PATH . $site . DS;
// 建立目录
IFile::mkdir(self::$torrentDir);
self::links();
}
/**
* 连接远端RPC服务器
*
* @param string
* @return array
*/
public static function links()
{
if (self::$workingMode === 1 && empty(self::$links)) {
foreach (self::$clients as $k => $v) {
// 跳过未配置的客户端
if (empty($v['username']) || empty($v['password'])) {
unset(self::$clients[$k]);
echo "clients_".$k." 用户名或密码未配置,已跳过 \n\n";
continue;
}
try {
switch ($v['type']) {
case 'transmission':
self::$links[$k]['rpc'] = new TransmissionRPC($v['host'], $v['username'], $v['password']);
$result = self::$links[$k]['rpc']->sstats();
print $v['type'].':'.$v['host']." Rpc连接成功 [{$result->result}] \n";
break;
case 'qBittorrent':
self::$links[$k]['rpc'] = new qBittorrent($v['host'], $v['username'], $v['password']);
$result = self::$links[$k]['rpc']->appVersion();
print $v['type'].':'.$v['host']." Rpc连接成功 [{$result}] \n";
break;
case 'uTorrent':
self::$links[$k]['rpc'] = new uTorrent($v['host'], $v['username'], $v['password']);
$result = self::$links[$k]['rpc']->getBuild();
print $v['type'].':'.$v['host']." Rpc连接 [{$result}] \n";
break;
default:
echo '[ERROR] '.$v['type'];
exit(1);
break;
}
self::$links[$k]['type'] = $v['type'];
self::$links[$k]['downloadDir'] = $v['downloadDir'];
} catch (Exception $e) {
echo '[ERROR] ' . $e->getMessage() . PHP_EOL;
exit(1);
}
}
}
return true;
}
/**
* @brief 添加下载任务
* @param string $torrent 种子元数据
* @param string $save_path 保存路径
* @return bool
*/
public static function add($torrent, $save_path = '', $extra_options = array())
{
switch ((int)self::$workingMode) {
case 0: // watch默认工作模式
// 复制到watch目录
copy($torrent, $save_path);
if (is_file($save_path)) {
print "********watch模式,下载任务添加成功 \n\n";
return true;
} else {
print "-----watch模式,下载任务添加失败!!! \n\n";
}
break;
case 1: //负载均衡模式
try {
$is_url = false;
if ((strpos($torrent, 'http://')===0) || (strpos($torrent, 'https://')===0) || (strpos($torrent, 'magnet:?xt=urn:btih:')===0)) {
$is_url = true;
}
// 负载均衡
$rpcKey = self::$RPC_Key;
echo '选中:负载均衡'.$rpcKey."\n";
self::rpcSelect();
// 调试
#p($result);
// 下载服务器类型 判断
$type = self::$links[$rpcKey]['type'];
switch ($type) {
case 'transmission':
if ($is_url) {
echo 'add';
$result = self::$links[$rpcKey]['rpc']->add($torrent, self::$links[$rpcKey]['downloadDir'], $extra_options); // 种子URL添加下载任务
} else {
echo 'add_metainfo';
$result = self::$links[$rpcKey]['rpc']->add_metainfo($torrent, self::$links[$rpcKey]['downloadDir'], $extra_options); // 种子文件添加下载任务
}
$id = $name = '';
if (isset($result->arguments->torrent_duplicate)) {
$id = $result->arguments->torrent_duplicate->id;
$name = $result->arguments->torrent_duplicate->name;
} elseif (isset($result->arguments->torrent_added)) {
$id = $result->arguments->torrent_added->id;
$name = $result->arguments->torrent_added->name;
}
if (!$id) {
print "-----RPC添加种子任务,失败 [{$result->result}] \n\n";
} else {
print "********RPC添加下载任务成功 [{$result->result}] (id=$id) \n\n";
// 新添加的任务,开始
self::$links[$rpcKey]['rpc']->start($id);
return true;
}
break;
case 'qBittorrent':
if ($is_url) {
echo 'add';
$result = self::$links[$rpcKey]['rpc']->add($torrent, self::$links[$rpcKey]['downloadDir'], $extra_options); // 种子URL添加下载任务
} else {
echo 'add_metainfo';
$result = self::$links[$rpcKey]['rpc']->add_metainfo($torrent, self::$links[$rpcKey]['downloadDir'], $extra_options); // 种子文件添加下载任务
}
if ($result === 'Ok.') {
print "********RPC添加下载任务成功 [{$result}] \n\n";
return true;
} else {
print "-----RPC添加种子任务,失败 [{$result}] \n\n";
}
break;
default:
echo '[ERROR] '.$type;
break;
}
} catch (Exception $e) {
die('[ERROR] ' . $e->getMessage() . PHP_EOL);
}
break;
case 2:
echo "\n\n";
# 暂未开放
break;
default:
echo "\n\n";
break;
}
return false;
}
/**
* 负载均衡 选择算法
*
* @param
* @return
*/
public static function rpcSelect()
{
$clientsConut = count(self::$clients);
if ($clientsConut > 1) {
if ($clientsConut > (self::$RPC_Key+1)) {
self::$RPC_Key++;
} else {
self::$RPC_Key = 0;
}
}
}
/**
* @brief 种子处理函数
* @param array $data 种子数组
* Array
(
[id] => 118632
[h1] => CCTV5+ 2019 ATP Men's Tennis Final 20191115B HDTV 1080i H264-HDxxx
[title] => 央视体育赛事频道 2019年ATP男子网球年终总决赛 单打小组赛 纳达尔VS西西帕斯 20191115[优惠剩余时间:4时13分]
[details] => https://XXX.me/details.php?id=118632
[download] => https://XXX.me/download.php?id=118632
[filename] => 118632.torrent
[type] => 0
[sticky] => 1
[time] => Array
(
[0] => "2019-11-16 20:41:53">4时13分
[1] => "2019-11-16 14:41:53">1时<br />46分
)
[comments] => 0
[size] => 5232.64MB
[seeders] => 69
[leechers] => 10
[completed] => 93
[percentage] => 100%
[owner] => 匿名
)
* @return
*/
public static function call($data = array())
{
foreach ($data as $key => $value) {
// 控制台打印
echo '主标题:'.$value['h1']."\n";
echo '副标题:'.$value['title']."\n";
echo '详情页:'.$value['details']."\n";
if ($value['type'] != 0) {
echo "-----非免费,已忽略! \n\n";
continue;
}
if (isset($value['hr']) && ($value['hr'] == 1)) {
echo "-----HR种子,已忽略! \n\n";
continue;
}
// 下载任务的可选参数
$extra_options = array();
// 保存的文件名
$filename = $value['id'] . '.torrent';
// 默认watch工作模式,复制到此目录
$to = self::$watch . $filename;
// 种子完整存放路径
$torrentFile = self::$torrentDir . $filename;
if (is_file($torrentFile)) {
$fileSize = filesize($torrentFile); //失败会返回false 或 0(0代表上次下载失败)
if (!empty($fileSize)) {
//种子已经存在
echo '-----存在旧种子:'.$filename."\n\n";
continue;
}
// 删除下载错误的文件
IFile::unlink($torrentFile);
}
// 调用过滤函数
$isFilter = filter(self::$site, $value);
if (is_string($isFilter)) {
echo "-----" .$isFilter. "\n\n";
continue;
}
//种子不存在
echo '正在下载新种子... '.$value['download']." \n";
// 创建文件、下载种子以二进制写入
$content = '';
$content = download($value['download'], self::$cookies, self::$userAgent, self::$method);
#p($content);
// 文件句柄
$resource = fopen($torrentFile, "wb");
// 成功:返回写入字节数,失败返回false
$worldsnum = fwrite($resource, $content);
// 关闭
fclose($resource);
// 判断
if (is_bool($worldsnum)) {
print "种子下载失败!!! \n\n";
IFile::unlink($torrentFile);
continue;
} else {
print "成功下载种子" . $filename . ',共计:' . $worldsnum . "字节 \n";
sleep(mt_rand(2, 10));
$ret = false;
$rpcKey = self::$RPC_Key;
switch ((int)self::$workingMode) {
case 0: //默认工作模式
$ret = self::add($torrentFile, $to);
break;
case 1: //负载均衡模式
$type = self::$links[$rpcKey]['type'];
// 下载服务器类型
switch ($type) {
case 'transmission':
# code...
break;
case 'qBittorrent':
$extra_options['name'] = 'torrents';
$extra_options['filename'] = $filename;
$extra_options['autoTMM'] = 'false'; //关闭自动种子管理
break;
default:
# code...
break;
}
// 种子文件添加下载任务
$ret = self::add($content, $to, $extra_options);
break;
case 2:
echo "\n\n";
# 暂未开放
break;
default:
echo "\n\n";
break;
}
global $configALL;
if (isset($configALL['iyuu.cn']) && ($ret === true)) {
send(self::$site, $value);
}
}
}
return true;
}
}

@ -107,29 +107,29 @@ class TransmissionRPC implements AbstractClientInterface
* 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
)
);
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
)
);
/**
* Constants for torrent status
*/
const TR_STATUS_STOPPED = 0;
const TR_STATUS_CHECK_WAIT = 1;
const TR_STATUS_CHECK = 2;
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 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;
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;
/**
* Start one or more torrents
@ -139,9 +139,9 @@ class TransmissionRPC implements AbstractClientInterface
public function start($ids)
{
if (!is_array($ids)) {
$ids = array( $ids );
} // Convert $ids to an array if only a single id was passed
$request = array( "ids" => $ids );
$ids = array($ids);
} // Convert $ids to an array if only a single id was passed
$request = array("ids" => $ids);
return $this->request("torrent-start", $request);
}
@ -153,9 +153,9 @@ class TransmissionRPC implements AbstractClientInterface
public function stop($ids)
{
if (!is_array($ids)) {
$ids = array( $ids );
} // Convert $ids to an array if only a single id was passed
$request = array( "ids" => $ids );
$ids = array($ids);
} // Convert $ids to an array if only a single id was passed
$request = array("ids" => $ids);
return $this->request("torrent-stop", $request);
}
@ -167,9 +167,9 @@ class TransmissionRPC implements AbstractClientInterface
public function reannounce($ids)
{
if (!is_array($ids)) {
$ids = array( $ids );
} // Convert $ids to an array if only a single id was passed
$request = array( "ids" => $ids );
$ids = array($ids);
} // Convert $ids to an array if only a single id was passed
$request = array("ids" => $ids);
return $this->request("torrent-reannounce", $request);
}
@ -181,9 +181,9 @@ class TransmissionRPC implements AbstractClientInterface
public function verify($ids)
{
if (!is_array($ids)) {
$ids = array( $ids );
} // Convert $ids to an array if only a single id was passed
$request = array( "ids" => $ids );
$ids = array($ids);
} // Convert $ids to an array if only a single id was passed
$request = array("ids" => $ids);
return $this->request("torrent-verify", $request);
}
@ -196,48 +196,48 @@ class TransmissionRPC implements AbstractClientInterface
* @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
}
* 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
* }
*/
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
);
$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);
}
@ -267,13 +267,13 @@ class TransmissionRPC implements AbstractClientInterface
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);
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);
}
/**
@ -297,9 +297,11 @@ class TransmissionRPC implements AbstractClientInterface
* Either "filename" OR "metainfo" MUST be included.
* All other arguments are optional.
*
* @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
* @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())
{
@ -307,22 +309,24 @@ class TransmissionRPC implements AbstractClientInterface
$extra_options['download-dir'] = $save_path;
}
$extra_options['filename'] = $torrent_location;
return $this->request("torrent-add", $extra_options);
}
/**
* Add a torrent using the raw torrent data
*
* @param torrent_metainfo The raw, unencoded contents (metainfo) of a torrent
* @param save_path Folder to save torrent in
* @param extra options Optional extra torrent options
* @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())
{
$extra_options['download-dir'] = $save_path;
$extra_options['metainfo'] = base64_encode($torrent_metainfo);
return $this->request("torrent-add", $extra_options);
}
@ -345,12 +349,12 @@ class TransmissionRPC implements AbstractClientInterface
public function remove($ids, $delete_local_data = false)
{
if (!is_array($ids)) {
$ids = array( $ids );
} // Convert $ids to an array if only a single id was passed
$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
);
"ids" => $ids,
"delete-local-data" => $delete_local_data
);
return $this->request("torrent-remove", $request);
}
@ -364,16 +368,16 @@ class TransmissionRPC implements AbstractClientInterface
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
$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
);
"ids" => $ids,
"location" => $target_location,
"move" => $move_existing_data
);
return $this->request("torrent-set-location", $request);
}
/**
* 3.7. Renaming a Torrent's Path
*
@ -392,27 +396,28 @@ class TransmissionRPC implements AbstractClientInterface
* | (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 );
$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
);
"ids" => $ids,
"path" => $path,
"name" => $name
);
return $this->request("torrent-rename-path", $request);
}
@ -441,6 +446,8 @@ class TransmissionRPC implements AbstractClientInterface
* Set session variable(s)
*
* @param array of session variables to set
* @return mixed
* @throws TransmissionRPCException
*/
public function sset($arguments)
{
@ -452,6 +459,7 @@ class TransmissionRPC implements AbstractClientInterface
*
* @param int The integer "torrent status"
* @returns string The translated meaning
* @return string
*/
public function getStatusString($intstatus)
{
@ -504,43 +512,43 @@ class TransmissionRPC implements AbstractClientInterface
*/
/**
* 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)) {
if (mb_detect_encoding($value, "auto") !== 'UTF-8') {
$array[$index] = mb_convert_encoding($value, "UTF-8");
//utf8_encode( $value ); // Make sure all data is UTF-8 encoded for Transmission
}
}
}
} // 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)) {
if (mb_detect_encoding($value, "auto") !== '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;
}
@ -550,6 +558,7 @@ class TransmissionRPC implements AbstractClientInterface
*
* @param object The request result to clean
* @returns array The cleaned object
* @return array|object
*/
protected function cleanResultObject($object)
{
@ -557,11 +566,11 @@ class TransmissionRPC implements AbstractClientInterface
$return_as_array = false;
$array = $object;
if (!is_array($array)) {
$array = (array) $array;
$array = (array)$array;
}
foreach ($array as $index => $value) {
if (is_array($array[$index]) || is_object($array[$index])) {
$array[$index] = $this->cleanResultObject($array[$index]); // Recursion
$array[$index] = $this->cleanResultObject($array[$index]); // Recursion
}
if (strstr($index, '-')) {
$valid_index = str_replace('-', '_', $index);
@ -570,7 +579,7 @@ class TransmissionRPC implements AbstractClientInterface
$index = $valid_index;
}
// Might be an array, check index for digits, if so, an array should be returned
if (ctype_digit((string) $index)) {
if (ctype_digit((string)$index)) {
$return_as_array = true;
}
if (empty($value)) {
@ -578,15 +587,16 @@ class TransmissionRPC implements AbstractClientInterface
}
}
// Return array cast to object
return $return_as_array ? $array : (object) $array;
return $return_as_array ? $array : (object)$array;
}
/**
* 执行 rpc 请求
*
* @param string $method 请求类型/方法, 详见 $this->allowMethods
* @param array $arguments 附加参数, 可选
* @return mixed
* @throws TransmissionRPCException
*/
protected function request($method, $arguments = array())
{
@ -597,9 +607,9 @@ class TransmissionRPC implements AbstractClientInterface
if (!is_array($arguments)) {
throw new TransmissionRPCException('Arguments must be given as array', TransmissionRPCException::E_INVALIDARG);
}
$arguments = $this->cleanRequestData($arguments); // Sanitize input
$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()) {
@ -608,21 +618,21 @@ class TransmissionRPC implements AbstractClientInterface
}
$data = array(
'method' => $method,
'arguments' => $arguments
);
'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
);
'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_USERPWD, $this->username . ':' . $this->password);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
@ -635,8 +645,9 @@ class TransmissionRPC implements AbstractClientInterface
if (!$content) {
$content = json_encode(array('result' => 'failed'));
}
return $this->return_as_array ? json_decode($content, true) : $this->cleanResultObject(json_decode($content)); // Return the sanitized result
return $this->return_as_array ? json_decode($content, true) : $this->cleanResultObject(json_decode($content)); // Return the sanitized result
}
/**
* Performs an empty GET on the Transmission RPC to get the X-Transmission-Session-Id
* and store it in $this->session_id
@ -648,57 +659,57 @@ class TransmissionRPC implements AbstractClientInterface
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)
$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));
$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);
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);
}
$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);
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
} 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);
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
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]);
throw new TransmissionRPCException("Unexpected response from Transmission RPC: " . $stream_meta['wrapper_data'][0]);
}
return $this->session_id;
}
@ -716,17 +727,17 @@ class TransmissionRPC implements AbstractClientInterface
{
// server URL
$this->url = $url;
// Username & password
$this->username = $username;
$this->password = $password;
// Get the Transmission RPC_version
$this->rpc_version = self::sget()->arguments->rpc_version;
// Return As Array
$this->return_as_array = $return_as_array;
// Reset X-Transmission-Session-Id so we (re)fetch one
$this->session_id = null;
}

@ -36,7 +36,7 @@ class TransmissionRPCException extends \Exception
/**
* Exception constructor
*/
public function __construct($message = null, $code = 0, Exception $previous = null)
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', '>=')) {

@ -1,5 +1,7 @@
{
"require": {
"ext-json": "*",
"ext-mbstring": "*",
"owner888/phpspider": "^2.1",
"curl/curl": "^2.2"
},

@ -47,4 +47,4 @@ if (AutoReseed::$move != null) {
exit;
}
AutoReseed::call($hashArray);
AutoReseed::wechatMessage();
AutoReseed::wechatMessage();

Loading…
Cancel
Save