From 7315524056b10d565e6199a9c7cc9030ea1da341 Mon Sep 17 00:00:00 2001 From: Rhilip Date: Wed, 15 Jan 2020 21:44:00 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=BF=E7=94=A8php-cs-fixer=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E4=BB=A3=E7=A0=81=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- app/Class/Function.php | 431 ++++++------ app/Class/IFile.php | 543 +++++++-------- app/Class/Oauth.php | 23 +- app/Class/Rpc.php | 607 ++++++++-------- app/Class/TransmissionRPC.php | 1240 +++++++++++++++++---------------- app/Class/qBittorrent.php | 29 +- app/Class/uTorrent.php | 91 ++- app/config/config.sample.php | 572 +++++++-------- 9 files changed, 1804 insertions(+), 1734 deletions(-) diff --git a/.gitignore b/.gitignore index 8ddbddc..df534e3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ /php-7.2.12-nts /*.bat /*.sh -/vendor \ No newline at end of file +/vendor diff --git a/app/Class/Function.php b/app/Class/Function.php index 77ce203..a444bdd 100644 --- a/app/Class/Function.php +++ b/app/Class/Function.php @@ -2,23 +2,24 @@ /** * 调试函数 */ -function p($data, $echo=true){ - $str='******************************'."\n"; - // 如果是boolean或者null直接显示文字;否则print - if (is_bool($data)) { - $show_data=$data ? 'true' : 'false'; - }elseif (is_null($data)) { - $show_data='null'; - }else{ - $show_data=print_r($data,true); - } - $str.=$show_data; - $str.="\n".'******************************'."\n"; - if($echo){ - echo $str; - return null; - } - return $str; +function p($data, $echo=true) +{ + $str='******************************'."\n"; + // 如果是boolean或者null直接显示文字;否则print + if (is_bool($data)) { + $show_data=$data ? 'true' : 'false'; + } elseif (is_null($data)) { + $show_data='null'; + } else { + $show_data=print_r($data, true); + } + $str.=$show_data; + $str.="\n".'******************************'."\n"; + if ($echo) { + echo $str; + return null; + } + return $str; } /** @@ -26,21 +27,21 @@ function p($data, $echo=true){ */ function sc($text='', $desp='') { - global $configALL; - $token = $configALL['sc.ftqq.com']; - $desp = ($desp=='')?date("Y-m-d H:i:s") :$desp; - $postdata = http_build_query(array( - 'text' => $text, - 'desp' => $desp - )); - $opts = array('http' => array( - 'method' => 'POST', - 'header' => 'Content-type: application/x-www-form-urlencoded', - 'content' => $postdata - )); - $context = stream_context_create($opts); - $result = file_get_contents('http://sc.ftqq.com/'.$token.'.send', false, $context); - return $result; + global $configALL; + $token = $configALL['sc.ftqq.com']; + $desp = ($desp=='')?date("Y-m-d H:i:s") :$desp; + $postdata = http_build_query(array( + 'text' => $text, + 'desp' => $desp + )); + $opts = array('http' => array( + 'method' => 'POST', + 'header' => 'Content-type: application/x-www-form-urlencoded', + 'content' => $postdata + )); + $context = stream_context_create($opts); + $result = file_get_contents('http://sc.ftqq.com/'.$token.'.send', false, $context); + return $result; } /** @@ -48,72 +49,72 @@ function sc($text='', $desp='') */ function ff($text='', $desp='') { - global $configALL; - $token = $configALL['iyuu.cn']; - $desp = ($desp=='')?date("Y-m-d H:i:s") :$desp; - $postdata = http_build_query(array( - 'text' => $text, - 'desp' => $desp - )); - $opts = array('http' => array( - 'method' => 'POST', - 'header' => 'Content-type: application/x-www-form-urlencoded', - 'content' => $postdata - )); - $context = stream_context_create($opts); - $result = file_get_contents('http://iyuu.cn/'.$token.'.send', false, $context); - return $result; + global $configALL; + $token = $configALL['iyuu.cn']; + $desp = ($desp=='')?date("Y-m-d H:i:s") :$desp; + $postdata = http_build_query(array( + 'text' => $text, + 'desp' => $desp + )); + $opts = array('http' => array( + 'method' => 'POST', + 'header' => 'Content-type: application/x-www-form-urlencoded', + 'content' => $postdata + )); + $context = stream_context_create($opts); + $result = file_get_contents('http://iyuu.cn/'.$token.'.send', false, $context); + return $result; } /** * 微信推送 爱语飞飞 * @param array $torrent 种子数组 - Array - ( - [id] => 118632 - [h1] => CCTV5+ 2019 ATP Men's Tennis Final 20191115B HDTV 1080i H264-HDSTV - [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时
46分 - ) - [comments] => 0 - [size] => 5232.64MB - [seeders] => 69 - [leechers] => 10 - [completed] => 93 - [percentage] => 100% - [owner] => 匿名 - ) + Array + ( + [id] => 118632 + [h1] => CCTV5+ 2019 ATP Men's Tennis Final 20191115B HDTV 1080i H264-HDSTV + [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时
46分 + ) + [comments] => 0 + [size] => 5232.64MB + [seeders] => 69 + [leechers] => 10 + [completed] => 93 + [percentage] => 100% + [owner] => 匿名 + ) */ function send($site = '', $torrent = array()) { - $br = "\r\n"; - $text = $site. ' 免费:' .$torrent['filename']. ',添加成功'; - $desp = '主标题:'.$torrent['h1'] . $br; + $br = "\r\n"; + $text = $site. ' 免费:' .$torrent['filename']. ',添加成功'; + $desp = '主标题:'.$torrent['h1'] . $br; - if ( isset($torrent['title']) ) { - $desp .= '副标题:'.$torrent['title']. $br; - } - if ( isset($torrent['size']) ) { - $desp .= '大小:'.$torrent['size']. $br; - } - if ( isset($torrent['seeders']) ) { - $desp .= '做种数:'.$torrent['seeders']. $br; - } - if ( isset($torrent['leechers']) ) { - $desp .= '下载数:'.$torrent['leechers']. $br; - } - if ( isset($torrent['owner']) ) { - $desp .= '发布者:'.$torrent['owner']. $br; - } - return ff($text, $desp); + if (isset($torrent['title'])) { + $desp .= '副标题:'.$torrent['title']. $br; + } + if (isset($torrent['size'])) { + $desp .= '大小:'.$torrent['size']. $br; + } + if (isset($torrent['seeders'])) { + $desp .= '做种数:'.$torrent['seeders']. $br; + } + if (isset($torrent['leechers'])) { + $desp .= '下载数:'.$torrent['leechers']. $br; + } + if (isset($torrent['owner'])) { + $desp .= '发布者:'.$torrent['owner']. $br; + } + return ff($text, $desp); } /** @@ -124,34 +125,34 @@ function send($site = '', $torrent = array()) */ function download($url, $cookies, $useragent, $method = 'GET') { - $header = array( - "Content-Type:application/x-www-form-urlencoded", - 'User-Agent: '.$useragent); - $ch = curl_init(); - if($method === 'POST'){ - curl_setopt($ch, CURLOPT_POST, true ); - } - if(stripos($url, 'https://') !== FALSE) { - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); - curl_setopt($ch, CURLOPT_SSLVERSION, 1); - } - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_HTTPHEADER,$header); - curl_setopt($ch, CURLOPT_COOKIE,$cookies); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT,60); - curl_setopt($ch, CURLOPT_TIMEOUT,600); - $data = curl_exec($ch); - $status = curl_getinfo($ch); - curl_close($ch); - if (isset($status['http_code']) && $status['http_code'] == 200) { - return $data; - } - if (isset($status['http_code']) && $status['http_code'] == 302) { - return download($status['redirect_url'], $cookies, $useragent); - } - return $data; + $header = array( + "Content-Type:application/x-www-form-urlencoded", + 'User-Agent: '.$useragent); + $ch = curl_init(); + if ($method === 'POST') { + curl_setopt($ch, CURLOPT_POST, true); + } + if (stripos($url, 'https://') !== false) { + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($ch, CURLOPT_SSLVERSION, 1); + } + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HTTPHEADER, $header); + curl_setopt($ch, CURLOPT_COOKIE, $cookies); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); + curl_setopt($ch, CURLOPT_TIMEOUT, 600); + $data = curl_exec($ch); + $status = curl_getinfo($ch); + curl_close($ch); + if (isset($status['http_code']) && $status['http_code'] == 200) { + return $data; + } + if (isset($status['http_code']) && $status['http_code'] == 302) { + return download($status['redirect_url'], $cookies, $useragent); + } + return $data; } /** @@ -159,19 +160,20 @@ function download($url, $cookies, $useragent, $method = 'GET') * @param string $from 文件大小 * @return int 单位MB */ -function convertToMB($from){ - $number=substr($from,0,-2); - switch(strtoupper(substr($from,-2))){ +function convertToMB($from) +{ + $number=substr($from, 0, -2); + switch (strtoupper(substr($from, -2))) { case "KB": return $number/1024; case "MB": return $number; case "GB": - return $number*pow(1024,1); + return $number*pow(1024, 1); case "TB": - return $number*pow(1024,2); + return $number*pow(1024, 2); case "PB": - return $number*pow(1024,3); + return $number*pow(1024, 3); default: return $from; } @@ -182,91 +184,92 @@ function convertToMB($from){ * @param string $site 站点标识 * @param array $torrent 种子数组 * Array - ( - [id] => 118632 - [h1] => CCTV5+ 2019 ATP Men's Tennis Final 20191115B HDTV 1080i H264-HDSTV - [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时
46分 - ) - [comments] => 0 - [size] => 5232.64MB - [seeders] => 69 - [leechers] => 10 - [completed] => 93 - [percentage] => 100% - [owner] => 匿名 - ) + ( + [id] => 118632 + [h1] => CCTV5+ 2019 ATP Men's Tennis Final 20191115B HDTV 1080i H264-HDSTV + [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时
46分 + ) + [comments] => 0 + [size] => 5232.64MB + [seeders] => 69 + [leechers] => 10 + [completed] => 93 + [percentage] => 100% + [owner] => 匿名 + ) * @return bool 或 string false不过滤 */ -function filter($site = '', $torrent = array()){ - global $configALL; - $config = $configALL[$site]; - $filter = array(); - // 读取配置 - if (isset($configALL['default']['filter']) || isset($config['filter'])) { - $filter = isset($config['filter']) && $config['filter'] ? $config['filter'] : $configALL['default']['filter']; - }else { - return false; - } - $filename = $torrent['filename']; +function filter($site = '', $torrent = array()) +{ + global $configALL; + $config = $configALL[$site]; + $filter = array(); + // 读取配置 + if (isset($configALL['default']['filter']) || isset($config['filter'])) { + $filter = isset($config['filter']) && $config['filter'] ? $config['filter'] : $configALL['default']['filter']; + } else { + return false; + } + $filename = $torrent['filename']; - // 兼容性 - if ( empty($torrent['size']) ) { - return false; - } - // 大小过滤 - $size = convertToMB($torrent['size']); - $min = isset($filter['size']['min']) ? convertToMB($filter['size']['min']) : 0; - $max = isset($filter['size']['max']) ? convertToMB($filter['size']['max']) : 2097152; //默认 2097152MB = 2TB - if ($min > $size || $size > $max) { - return $filename. ' ' .$size. 'MB,被大小过滤'; - } + // 兼容性 + if (empty($torrent['size'])) { + return false; + } + // 大小过滤 + $size = convertToMB($torrent['size']); + $min = isset($filter['size']['min']) ? convertToMB($filter['size']['min']) : 0; + $max = isset($filter['size']['max']) ? convertToMB($filter['size']['max']) : 2097152; //默认 2097152MB = 2TB + if ($min > $size || $size > $max) { + return $filename. ' ' .$size. 'MB,被大小过滤'; + } - // 兼容性 - if ( empty($torrent['seeders']) ) { - return false; - } - // 种子数过滤 - $seeders = $torrent['seeders']; - $min = isset($filter['seeders']['min']) ? $filter['seeders']['min'] : 1; //默认 1 - $max = isset($filter['seeders']['max']) ? $filter['seeders']['max'] : 3; //默认 3 - if ($min > $seeders || $seeders > $max) { - return $filename. ' 当前做种' .$seeders. '人,被过滤'; - } + // 兼容性 + if (empty($torrent['seeders'])) { + return false; + } + // 种子数过滤 + $seeders = $torrent['seeders']; + $min = isset($filter['seeders']['min']) ? $filter['seeders']['min'] : 1; //默认 1 + $max = isset($filter['seeders']['max']) ? $filter['seeders']['max'] : 3; //默认 3 + if ($min > $seeders || $seeders > $max) { + return $filename. ' 当前做种' .$seeders. '人,被过滤'; + } - // 兼容性 - if ( empty($torrent['leechers']) ) { - return false; - } - // 下载数过滤 - $leechers = $torrent['leechers']; - $min = isset($filter['leechers']['min']) ? $filter['leechers']['min'] : 0; //默认 - $max = isset($filter['leechers']['max']) ? $filter['leechers']['max'] : 30000; //默认 - if ($min > $leechers || $leechers > $max) { - return $filename. ' 当前下载' .$leechers. '人,被过滤'; - } + // 兼容性 + if (empty($torrent['leechers'])) { + return false; + } + // 下载数过滤 + $leechers = $torrent['leechers']; + $min = isset($filter['leechers']['min']) ? $filter['leechers']['min'] : 0; //默认 + $max = isset($filter['leechers']['max']) ? $filter['leechers']['max'] : 30000; //默认 + if ($min > $leechers || $leechers > $max) { + return $filename. ' 当前下载' .$leechers. '人,被过滤'; + } - // 兼容性 - if ( empty($torrent['completed']) ) { - return false; - } - // 完成数过滤 - $completed = $torrent['completed']; - $min = isset($filter['completed']['min']) ? $filter['completed']['min'] : 0; //默认 - $max = isset($filter['completed']['max']) ? $filter['completed']['max'] : 30000; //默认 - if ($min > $completed || $completed > $max) { - return $filename. ' 已完成数' .$completed. '人,被过滤'; - } + // 兼容性 + if (empty($torrent['completed'])) { + return false; + } + // 完成数过滤 + $completed = $torrent['completed']; + $min = isset($filter['completed']['min']) ? $filter['completed']['min'] : 0; //默认 + $max = isset($filter['completed']['max']) ? $filter['completed']['max'] : 30000; //默认 + if ($min > $completed || $completed > $max) { + return $filename. ' 已完成数' .$completed. '人,被过滤'; + } - return false; + return false; } /** @@ -284,22 +287,23 @@ function oddFilter($var) */ function evenFilter($var) { - // 返回$var最后一个二进制位, + // 返回$var最后一个二进制位, // 为0则保留(偶数的二进制的最后一位肯定是0) - return(!($var & 1)); + return(!($var & 1)); } /** * 发布员签名 * 注意:同时配置iyuu.cn与secret时,优先使用secret。 */ -function sign( $timestamp ){ - global $configALL; - // 爱语飞飞 - $token = isset($configALL['iyuu.cn']) && $configALL['iyuu.cn'] ? $configALL['iyuu.cn'] : ''; - // 鉴权 - $token = isset($configALL['secret']) && $configALL['secret'] ? $configALL['secret'] : $token; - return sha1($timestamp . $token); +function sign($timestamp) +{ + global $configALL; + // 爱语飞飞 + $token = isset($configALL['iyuu.cn']) && $configALL['iyuu.cn'] ? $configALL['iyuu.cn'] : ''; + // 鉴权 + $token = isset($configALL['secret']) && $configALL['secret'] ? $configALL['secret'] : $token; + return sha1($timestamp . $token); } /** @@ -307,7 +311,8 @@ function sign( $timestamp ){ * token算法:IYUU + uid + T + sha1(openid+time+盐) * @param string $token 用户请求token */ -function getUid($token){ - //验证是否IYUU开头,strpos($token,'T')<15,token总长度小于60(40+10+5) - return (strlen($token)<60)&&(strpos($token,'IYUU')===0)&&(strpos($token,'T')<15) ? substr($token,4,strpos($token,'T')-4): false; +function getUid($token) +{ + //验证是否IYUU开头,strpos($token,'T')<15,token总长度小于60(40+10+5) + return (strlen($token)<60)&&(strpos($token, 'IYUU')===0)&&(strpos($token, 'T')<15) ? substr($token, 4, strpos($token, 'T')-4): false; } diff --git a/app/Class/IFile.php b/app/Class/IFile.php index 4fa3322..f82a990 100644 --- a/app/Class/IFile.php +++ b/app/Class/IFile.php @@ -10,323 +10,290 @@ */ class IFile { - private $resource = null; //文件资源句柄 + private $resource = null; //文件资源句柄 - /** - * @brief 构造函数,打开资源流,并独占锁定 - * @param String $fileName 文件路径名 - * @param String $mode 操作方式,默认为读操作,可供选择的项为:r,r+,w+,w+,a,a+ - * @note $mod,'r' 只读方式打开,将文件指针指向文件头 - * 'r+' 读写方式打开,将文件指针指向文件头 - * 'w' 写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。 - * 'w+' 读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。 - * 'a' 写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。 - * 'a+' 读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。 - */ - function __construct($fileName,$mode='r') - { - $dirName = dirname($fileName); - $baseName = basename($fileName); - - //检查并创建文件夹 - self::mkdir($dirName); + /** + * @brief 构造函数,打开资源流,并独占锁定 + * @param String $fileName 文件路径名 + * @param String $mode 操作方式,默认为读操作,可供选择的项为:r,r+,w+,w+,a,a+ + * @note $mod,'r' 只读方式打开,将文件指针指向文件头 + * 'r+' 读写方式打开,将文件指针指向文件头 + * 'w' 写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。 + * 'w+' 读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。 + * 'a' 写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。 + * 'a+' 读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。 + */ + public function __construct($fileName, $mode='r') + { + $dirName = dirname($fileName); + $baseName = basename($fileName); - $this->resource = fopen($fileName,$mode.'b'); - if($this->resource) - { - flock($this->resource,LOCK_EX); - } - } + //检查并创建文件夹 + self::mkdir($dirName); - /** - * @brief 获取文件内容 - * @return String 文件内容 - */ - public function read() - { - $content = null; - while(!feof($this->resource)) - { - $content.= fread($this->resource,1024); - } - return $content; - } + $this->resource = fopen($fileName, $mode.'b'); + if ($this->resource) { + flock($this->resource, LOCK_EX); + } + } - /** - * @brief 文件写入操作 - * @param String $content 要写入的文件内容 - * @return Int or false 写入的字符数; false:写入失败; - */ - public function write($content) - { - $worldsnum = fwrite($this->resource,$content); - $this->save(); - return is_bool($worldsnum) ? false : $worldsnum; - } + /** + * @brief 获取文件内容 + * @return String 文件内容 + */ + public function read() + { + $content = null; + while (!feof($this->resource)) { + $content.= fread($this->resource, 1024); + } + return $content; + } - /** - * @brief 清空目录下的所有文件 - * @return bool false:失败; true:成功; - */ - public static function clearDir($dir) - { - if($dir[0] != '.' && is_dir($dir) && is_writable($dir)) - { - $dirRes = opendir($dir); - while( false !== ($fileName = readdir($dirRes)) ) - { - if($fileName[0] !== '.') - { - $fullpath = $dir.'/'.$fileName; - if(is_file($fullpath)) - { - self::unlink($fullpath); - } - else - { - self::clearDir($fullpath); - rmdir($fullpath); - } - } - } - closedir($dirRes); - return true; - } - else - { - return false; - } - } + /** + * @brief 文件写入操作 + * @param String $content 要写入的文件内容 + * @return Int or false 写入的字符数; false:写入失败; + */ + public function write($content) + { + $worldsnum = fwrite($this->resource, $content); + $this->save(); + return is_bool($worldsnum) ? false : $worldsnum; + } - /** - * @brief 获取文件信息 - * @param String $fileName 文件路径 - * @return array or null array:文件信息; null:文件不存在; - */ - public static function getInfo($fileName) - { - if(is_file($fileName)) - return stat($fileName); + /** + * @brief 清空目录下的所有文件 + * @return bool false:失败; true:成功; + */ + public static function clearDir($dir) + { + if ($dir[0] != '.' && is_dir($dir) && is_writable($dir)) { + $dirRes = opendir($dir); + while (false !== ($fileName = readdir($dirRes))) { + if ($fileName[0] !== '.') { + $fullpath = $dir.'/'.$fileName; + if (is_file($fullpath)) { + self::unlink($fullpath); + } else { + self::clearDir($fullpath); + rmdir($fullpath); + } + } + } + closedir($dirRes); + return true; + } else { + return false; + } + } - else - return null; - } + /** + * @brief 获取文件信息 + * @param String $fileName 文件路径 + * @return array or null array:文件信息; null:文件不存在; + */ + public static function getInfo($fileName) + { + if (is_file($fileName)) { + return stat($fileName); + } else { + return null; + } + } - /** - * @brief 创建文件夹 - * @param String $path 路径 - * @param int $chmod 文件夹权限 - * @note $chmod 参数不能是字符串(加引号),否则linux会出现权限问题 - */ - public static function mkdir($path,$chmod=0777) - { - return is_dir($path) or (self::mkdir(dirname($path),$chmod) and mkdir($path,$chmod)); - } + /** + * @brief 创建文件夹 + * @param String $path 路径 + * @param int $chmod 文件夹权限 + * @note $chmod 参数不能是字符串(加引号),否则linux会出现权限问题 + */ + public static function mkdir($path, $chmod=0777) + { + return is_dir($path) or (self::mkdir(dirname($path), $chmod) and mkdir($path, $chmod)); + } - /** - * @brief 复制文件 - * @param String $from 源文件路径 - * @param String $to 目标文件路径 - * @param String $mod 操作模式,c:复制(默认); x:剪切(删除$from文件) - * @return bool 操作结果 true:成功; false:失败; - */ - public static function copy($from,$to,$mode = 'c') - { - $dir = dirname($to); + /** + * @brief 复制文件 + * @param String $from 源文件路径 + * @param String $to 目标文件路径 + * @param String $mod 操作模式,c:复制(默认); x:剪切(删除$from文件) + * @return bool 操作结果 true:成功; false:失败; + */ + public static function copy($from, $to, $mode = 'c') + { + $dir = dirname($to); - //创建目录 - self::mkdir($dir); + //创建目录 + self::mkdir($dir); - copy($from,$to); + copy($from, $to); - if(is_file($to)) - { - if($mode == 'x') - { - self::unlink($from); - } - return true; - } - else - { - return false; - } - } + if (is_file($to)) { + if ($mode == 'x') { + self::unlink($from); + } + return true; + } else { + return false; + } + } - /** - * @brief 删除文件 - * @param String $fileName 文件路径 - * @return bool 操作结果 false:删除失败; - */ - public static function unlink($fileName) - { - if(is_file($fileName) && is_writable($fileName)) - { - return unlink($fileName); - } - else - return false; - } + /** + * @brief 删除文件 + * @param String $fileName 文件路径 + * @return bool 操作结果 false:删除失败; + */ + public static function unlink($fileName) + { + if (is_file($fileName) && is_writable($fileName)) { + return unlink($fileName); + } else { + return false; + } + } - /** - * @brief 删除$dir文件夹 或者 其下所有文件 - * @param String $dir 文件路径 - * @param bool $recursive 是否强制删除,如果强制删除则递归删除该目录下的全部文件,默认为false - * @return bool true:删除成功; false:删除失败; - */ - public static function rmdir($dir,$recursive = false) - { - if(is_dir($dir) && is_writable($dir)) - { - //强制删除 - if($recursive == true) - { - self::clearDir($dir); - return self::rmdir($dir,false); - } + /** + * @brief 删除$dir文件夹 或者 其下所有文件 + * @param String $dir 文件路径 + * @param bool $recursive 是否强制删除,如果强制删除则递归删除该目录下的全部文件,默认为false + * @return bool true:删除成功; false:删除失败; + */ + public static function rmdir($dir, $recursive = false) + { + if (is_dir($dir) && is_writable($dir)) { + //强制删除 + if ($recursive == true) { + self::clearDir($dir); + return self::rmdir($dir, false); + } - //非强制删除 - else - { - if(rmdir($dir)) - { - return true; - } - else - { - return false; - } - } - } - } + //非强制删除 + else { + if (rmdir($dir)) { + return true; + } else { + return false; + } + } + } + } - /** - * @brief 获取文件类型 - * @param String $fileName 文件名 - * @return String $filetype 文件类型 - * @note 如果文件不存在,返回false,如果文件后缀名不在识别列表之内,返回NULL,对于docx及elsx格式文档识别在会出现识别为ZIP格式的错误,这是office2007的bug目前尚未修复,请谨慎使用 - */ - public static function getFileType($fileName) - { - $filetype = null; - if(!is_file($fileName)) - { - return false; - } + /** + * @brief 获取文件类型 + * @param String $fileName 文件名 + * @return String $filetype 文件类型 + * @note 如果文件不存在,返回false,如果文件后缀名不在识别列表之内,返回NULL,对于docx及elsx格式文档识别在会出现识别为ZIP格式的错误,这是office2007的bug目前尚未修复,请谨慎使用 + */ + public static function getFileType($fileName) + { + $filetype = null; + if (!is_file($fileName)) { + return false; + } - $fileRes = fopen($fileName,"rb"); - if(!$fileRes) - { - return false; - } + $fileRes = fopen($fileName, "rb"); + if (!$fileRes) { + return false; + } $bin= fread($fileRes, 2); fclose($fileRes); - if($bin != null) - { - $strInfo = unpack("C2chars", $bin); - $typeCode = intval($strInfo['chars1'].$strInfo['chars2']); - $typelist = self::getTypeList(); - foreach($typelist as $val) - { - if(strtolower($val[0]) == strtolower($typeCode)) - { - if($val[0] == 8075) - { - return array('zip','docx','xlsx'); - } - else - { - return $val[1]; - } - } - } + if ($bin != null) { + $strInfo = unpack("C2chars", $bin); + $typeCode = intval($strInfo['chars1'].$strInfo['chars2']); + $typelist = self::getTypeList(); + foreach ($typelist as $val) { + if (strtolower($val[0]) == strtolower($typeCode)) { + if ($val[0] == 8075) { + return array('zip','docx','xlsx'); + } else { + return $val[1]; + } + } + } } - return $filetype; - } + return $filetype; + } - /** - * @brief 获取文件类型映射关系 + /** + * @brief 获取文件类型映射关系 * @return array 文件类型映射关系数组 */ public static function getTypeList() { - return array( - array('255216','jpg'), - array('13780','png'), - array('7173','gif'), - array('6677','bmp'), - array('6063','xml'), - array('60104','html'), - array('208207','xls/doc'), - array('8075','zip'), - array('8075','docx'), - array('8075','xlsx'), - array("8297","rar"), - ); + return array( + array('255216','jpg'), + array('13780','png'), + array('7173','gif'), + array('6677','bmp'), + array('6063','xml'), + array('60104','html'), + array('208207','xls/doc'), + array('8075','zip'), + array('8075','docx'), + array('8075','xlsx'), + array("8297","rar"), + ); } - /** - * @brief 获取文件大小 - * @param String $fileName 文件名 - * @return Int 文件大小的字节数,如果文件无效则返回 NULL - */ - public static function getFileSize($fileName) - { - return is_file($fileName) ? filesize($fileName):null; - } + /** + * @brief 获取文件大小 + * @param String $fileName 文件名 + * @return Int 文件大小的字节数,如果文件无效则返回 NULL + */ + public static function getFileSize($fileName) + { + return is_file($fileName) ? filesize($fileName):null; + } - /** - * @brief 检测文件夹是否为空 - * @param String $dir 路径地址 - * @return bool true:$dir为空目录; false:$dir为非空目录; - */ - public static function isEmptyDir($dir) - { - if(is_dir($dir)) - { - $isEmpty = true; - $dirRes = opendir($dir); - while(false !== ($fileName = readdir($dirRes))) - { - if($fileName!='.' && $fileName!='..') - { - $isEmpty = false; - break; - } - } - closedir($dirRes); - return $isEmpty; - } - } + /** + * @brief 检测文件夹是否为空 + * @param String $dir 路径地址 + * @return bool true:$dir为空目录; false:$dir为非空目录; + */ + public static function isEmptyDir($dir) + { + if (is_dir($dir)) { + $isEmpty = true; + $dirRes = opendir($dir); + while (false !== ($fileName = readdir($dirRes))) { + if ($fileName!='.' && $fileName!='..') { + $isEmpty = false; + break; + } + } + closedir($dirRes); + return $isEmpty; + } + } - /** - * @brief 释放文件锁定 - */ - public function save() - { - flock($this->resource,LOCK_UN); - } + /** + * @brief 释放文件锁定 + */ + public function save() + { + flock($this->resource, LOCK_UN); + } - /** - * @brief 获取文件扩展名 - * @param String $fileName 文件名 - * @return String 文件后缀名 - */ - public static function getFileSuffix($fileName) - { - $fileInfoArray = pathinfo($fileName); - return $fileInfoArray['extension']; - } + /** + * @brief 获取文件扩展名 + * @param String $fileName 文件名 + * @return String 文件后缀名 + */ + public static function getFileSuffix($fileName) + { + $fileInfoArray = pathinfo($fileName); + return $fileInfoArray['extension']; + } - /** - * @brief 析构函数,释放文件连接句柄 - */ - function __destruct() - { - if(is_resource($this->resource)) - { - fclose($this->resource); - } - } -} \ No newline at end of file + /** + * @brief 析构函数,释放文件连接句柄 + */ + public function __destruct() + { + if (is_resource($this->resource)) { + fclose($this->resource); + } + } +} diff --git a/app/Class/Oauth.php b/app/Class/Oauth.php index fff4630..c8e561b 100644 --- a/app/Class/Oauth.php +++ b/app/Class/Oauth.php @@ -3,7 +3,9 @@ * IYUU用户注册、认证 */ use Curl\Curl; -class Oauth{ + +class Oauth +{ // 合作的站点 public static $sites = ['ourbits']; // 爱语飞飞token @@ -17,13 +19,14 @@ class Oauth{ /** * 初始化配置 */ - public static function init(){ + public static function init() + { global $configALL; foreach (self::$sites as $name) { - if (isset($configALL[$name]['passkey']) && $configALL[$name]['passkey'] && isset($configALL[$name]['id']) && $configALL[$name]['id'] ) { + if (isset($configALL[$name]['passkey']) && $configALL[$name]['passkey'] && isset($configALL[$name]['id']) && $configALL[$name]['id']) { self::$token = self::getSign(); self::$user_id = $configALL[$name]['id']; - self::$passkey = sha1( $configALL[$name]['passkey'] ); // 避免泄露用户passkey秘钥 + self::$passkey = sha1($configALL[$name]['passkey']); // 避免泄露用户passkey秘钥 self::$site = $name; return true; } @@ -35,7 +38,8 @@ class Oauth{ /** * 从配置文件内读取爱语飞飞token作为鉴权参数 */ - public static function getSign(){ + public static function getSign() + { global $configALL; // 爱语飞飞 $token = isset($configALL['iyuu.cn']) && $configALL['iyuu.cn'] ? $configALL['iyuu.cn'] : ''; @@ -51,9 +55,10 @@ class Oauth{ * 作用:在服务器端实现微信用户与合作站点用户id的关联 * 参数:爱语飞飞token + 合作站点用户id + sha1(合作站点密钥passkey) + 合作站点标识 */ - public static function login($apiUrl = ''){ + public static function login($apiUrl = '') + { $is_oauth = self::init(); - if ( $is_oauth ) { + if ($is_oauth) { $curl = new Curl(); $curl->setOpt(CURLOPT_SSL_VERIFYPEER, false); $data = [ @@ -66,6 +71,6 @@ class Oauth{ p($res->response); return true; } - return false; + return false; } -} \ No newline at end of file +} diff --git a/app/Class/Rpc.php b/app/Class/Rpc.php index 76186e8..b259f28 100644 --- a/app/Class/Rpc.php +++ b/app/Class/Rpc.php @@ -4,78 +4,79 @@ */ class Rpc { - /** + /** * 版本号 * @var string */ const VER = '0.0.1'; - // 下载种子的请求类型 GET POST - public static $method = 'GET'; - // RPC连接池 - public static $links = array(); - /** + // 下载种子的请求类型 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 $site = ''; + /** * 负载均衡 控制变量 */ public static $RPC_Key = 0; - /** + /** * 退出状态码 */ - public static $ExitCode = 0; - /** + public static $ExitCode = 0; + /** * 初始化 */ - public static function init($site = '', $method = 'GET'){ - global $configALL; + public static function init($site = '', $method = 'GET') + { + global $configALL; - self::$site = $site; - self::$method = strtoupper($method); + 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(); - } + $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 @@ -83,140 +84,138 @@ class Rpc */ 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; + 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 - */ + /** + * @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; + 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; } /** @@ -227,142 +226,142 @@ class Rpc */ 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时
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; - } + $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时
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; + } } diff --git a/app/Class/TransmissionRPC.php b/app/Class/TransmissionRPC.php index 0d5f450..5e50336 100644 --- a/app/Class/TransmissionRPC.php +++ b/app/Class/TransmissionRPC.php @@ -13,7 +13,7 @@ * 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 . */ @@ -29,8 +29,9 @@ /** * A friendly little version check... */ -if ( version_compare( PHP_VERSION, TransmissionRPC::MIN_PHPVER, '<' ) ) - die( "The TransmissionRPC class requires PHP version {TransmissionRPC::TRANSMISSIONRPC_MIN_PHPVER} or above." . PHP_EOL ); +if (version_compare(PHP_VERSION, TransmissionRPC::MIN_PHPVER, '<')) { + die("The TransmissionRPC class requires PHP version {TransmissionRPC::TRANSMISSIONRPC_MIN_PHPVER} or above." . PHP_EOL); +} /** * Transmission bittorrent client/daemon RPC communication class @@ -44,627 +45,687 @@ if ( version_compare( PHP_VERSION, TransmissionRPC::MIN_PHPVER, '<' ) ) */ class TransmissionRPC { - /** - * User agent used in all http communication - */ - const HTTP_UA = 'TransmissionRPC for PHP/0.3'; - - /** - * Minimum PHP version required - * 5.2.10 implemented the required http stream ignore_errors option - */ - const MIN_PHPVER = '5.2.10'; - - /** - * 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 = ''; - - /** - * Return results as an array, or an object (default) - * @var bool - */ - public $return_as_array = false; - - /** - * 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 used in all http communication + */ + const HTTP_UA = 'TransmissionRPC for PHP/0.3'; + + /** + * Minimum PHP version required + * 5.2.10 implemented the required http stream ignore_errors option + */ + const MIN_PHPVER = '5.2.10'; + + /** + * 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 = ''; + + /** + * Return results as an array, or an object (default) + * @var bool + */ + public $return_as_array = false; + + /** + * 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 ) ); - /** - * 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; - - /** - * Start one or more torrents - * - * @param int|array ids A list of transmission torrent ids - */ - 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 ); - return $this->request( "torrent-start", $request ); - } - - /** - * Stop one or more torrents - * - * @param int|array ids A list of transmission torrent ids - */ - 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 ); - return $this->request( "torrent-stop", $request ); - } - - /** - * Reannounce one or more torrents - * - * @param int|array ids A list of transmission torrent ids - */ - 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 ); - return $this->request( "torrent-reannounce", $request ); - } - - /** - * Verify one or more torrents - * - * @param int|array ids A list of transmission torrent ids - */ - 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 ); - 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 - } + /** + * 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; + + /** + * Start one or more torrents + * + * @param int|array ids A list of transmission torrent ids + */ + 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 ); + return $this->request("torrent-start", $request); + } - 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 + /** + * Stop one or more torrents + * + * @param int|array ids A list of transmission torrent ids + */ + 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 ); + return $this->request("torrent-stop", $request); + } + + /** + * Reannounce one or more torrents + * + * @param int|array ids A list of transmission torrent ids + */ + 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 ); + return $this->request("torrent-reannounce", $request); + } + + /** + * Verify one or more torrents + * + * @param int|array ids A list of transmission torrent ids + */ + 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 ); + 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 + } + */ + 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 - */ - 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 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_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-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 + */ + 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 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_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 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 - */ - 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); + } + + /** + * 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 + */ + 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 ); - } - - /* 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 ); - } - - /** - * Remove torrent from transmission - * - * @param bool delete_local_data Also remove local data? - * @param int|array ids A list of transmission torrent ids - */ - 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 - $request = array( + 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); + } + + /** + * Remove torrent from transmission + * + * @param bool delete_local_data Also remove local data? + * @param int|array ids A list of transmission torrent ids + */ + 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 + $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 - */ - 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( + 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 + */ + 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 - */ - 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 ); + 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 + */ + 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( + $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 - */ - 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 - */ - 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 $this->request("torrent-rename-path", $request); + } + + + /** + * Retrieve session statistics + * + * @returns array of statistics + */ + public function sstats() + { + return $this->request("session-stats", array()); } - return "Unknown"; - } + /** + * 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 + */ + public function sset($arguments) + { + return $this->request("session-set", $arguments); + } - /** - * Here be dragons (Internal methods) - */ + /** + * Return the interpretation of the torrent status + * + * @param int The integer "torrent status" + * @returns string The translated meaning + */ + 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"; + } - /** - * 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 - */ - 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 ) + /** + * 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 + */ + protected function cleanRequestData($array) { - 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_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 - } + 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; - } - - /** - * Clean up the result object. Replaces all minus(-) characters in the object properties with underscores - * and converts any object with any all-digit property names to an array. - * - * @param object The request result to clean - * @returns array The cleaned object - */ - protected function cleanResultObject ( $object ) - { - // Prepare and cast object to array - $return_as_array = false; - $array = $object; - if ( !is_array( $array ) ) $array = (array) $array; - foreach ( $array as $index => $value ) + return $array; + } + + /** + * Clean up the result object. Replaces all minus(-) characters in the object properties with underscores + * and converts any object with any all-digit property names to an array. + * + * @param object The request result to clean + * @returns array The cleaned object + */ + protected function cleanResultObject($object) { - if( is_array( $array[$index] ) || is_object( $array[$index] ) ) - { - $array[$index] = $this->cleanResultObject( $array[$index] ); // Recursion - } - if ( strstr( $index, '-' ) ) - { - $valid_index = str_replace( '-', '_', $index ); - $array[$valid_index] = $array[$index]; - unset( $array[$index] ); - $index = $valid_index; - } - // Might be an array, check index for digits, if so, an array should be returned - if ( ctype_digit( (string) $index ) ) { $return_as_array = true; } - if ( empty( $value ) ) unset( $array[$index] ); + // Prepare and cast object to array + $return_as_array = false; + $array = $object; + if (!is_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 + } + if (strstr($index, '-')) { + $valid_index = str_replace('-', '_', $index); + $array[$valid_index] = $array[$index]; + unset($array[$index]); + $index = $valid_index; + } + // Might be an array, check index for digits, if so, an array should be returned + if (ctype_digit((string) $index)) { + $return_as_array = true; + } + if (empty($value)) { + unset($array[$index]); + } + } + // Return array cast to object + return $return_as_array ? $array : (object) $array; } - // Return array cast to object - return $return_as_array ? $array : (object) $array; - } - /** - * 执行 rpc 请求 - * - * @param $method 请求类型/方法, 详见 $this->allowMethods - * @param array $arguments 附加参数, 可选 - * @return mixed - */ - 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 ); + /** + * 执行 rpc 请求 + * + * @param $method 请求类型/方法, 详见 $this->allowMethods + * @param array $arguments 附加参数, 可选 + * @return mixed + */ + 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 + $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 ); + // 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( + $data = array( 'method' => $method, 'arguments' => $arguments ); - $header = array( + $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 = json_encode(array('result' => 'failed')); - 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 - * - * @return string - */ - public function GetSessionID() - { - if( !$this->url ) - throw new TransmissionRPCException( "Class must be initialized before GetSessionID() can be called.", TransmissionRPCException::E_INVALIDARG ); + $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 = json_encode(array('result' => 'failed')); + } + 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 + * + * @return string + */ + public function GetSessionID() + { + if (!$this->url) { + throw new TransmissionRPCException("Class must be initialized before GetSessionID() can be called.", TransmissionRPCException::E_INVALIDARG); + } - // Setup the context + // Setup the context $contextopts = $this->default_context_opts; // Start with the defaults // Make sure it's blank/empty (reset) - $this->session_id = null; + $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 ) ); + // 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 ); + 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 ); + $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 - { + // 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; + 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]); } - } - 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; } - return $this->session_id; - } - - /** - * Takes the connection parameters - * - * TODO: Sanitize username, password, and URL - * - * @param string $url - * @param string $username - * @param string $password - */ - public function __construct( $url = 'http://localhost:9091/transmission/rpc', $username = null, $password = null, $return_as_array = false ) - { - // server URL - $this->url = $url; + + /** + * Takes the connection parameters + * + * TODO: Sanitize username, password, and URL + * + * @param string $url + * @param string $username + * @param string $password + */ + public function __construct($url = 'http://localhost:9091/transmission/rpc', $username = null, $password = null, $return_as_array = false) + { + // server URL + $this->url = $url; - // Username & password - $this->username = $username; - $this->password = $password; + // Username & password + $this->username = $username; + $this->password = $password; - // Get the Transmission RPC_version - $this->rpc_version = self::sget()->arguments->rpc_version; + // Get the Transmission RPC_version + $this->rpc_version = self::sget()->arguments->rpc_version; - // Return As Array - $this->return_as_array = $return_as_array; + // Return As Array + $this->return_as_array = $return_as_array; - // Reset X-Transmission-Session-Id so we (re)fetch one - $this->session_id = null; - } + // Reset X-Transmission-Session-Id so we (re)fetch one + $this->session_id = null; + } } /** @@ -672,37 +733,36 @@ class TransmissionRPC */ 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 ); - } + /** + * 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); + } + } } - -?> diff --git a/app/Class/qBittorrent.php b/app/Class/qBittorrent.php index aa0e747..d61d0f5 100644 --- a/app/Class/qBittorrent.php +++ b/app/Class/qBittorrent.php @@ -1,5 +1,6 @@ null, '2' => '/api/v2/app/setPreferences' ], - 'defaultSavePath' => [ + 'defaultSavePath' => [ '1' => null, '2' => '/api/v2/app/defaultSavePath' ], @@ -72,7 +73,7 @@ class qBittorrent public function __construct($url='', $username='', $password='', $api_version = 2, $debug = false) { $this->debug = $debug; - $this->url = rtrim($url,'/'); + $this->url = rtrim($url, '/'); $this->username = $username; $this->password = $password; $this->api_version = $api_version; @@ -130,29 +131,33 @@ class qBittorrent */ public function add($torrent_url, $save_path = '', $extra_options = array()) { - if(!empty($save_path)) $extra_options['savepath'] = $save_path; + if (!empty($save_path)) { + $extra_options['savepath'] = $save_path; + } $extra_options['urls'] = $torrent_url; #$extra_options['skip_checking'] = 'true'; //跳校验 // 关键 上传文件流 multipart/form-data【严格按照api文档编写】 $post_data = $this->buildUrls($extra_options); #p($post_data); // 设置请求头 - $this->curl->setHeader('Content-Type','multipart/form-data; boundary='.$this->delimiter); - $this->curl->setHeader('Content-Length',strlen($post_data)); + $this->curl->setHeader('Content-Type', 'multipart/form-data; boundary='.$this->delimiter); + $this->curl->setHeader('Content-Length', strlen($post_data)); return $this->postData('torrent_add', $post_data); } - public function add_metainfo($torrent_metainfo, $save_path = '', $extra_options = array()) + public function add_metainfo($torrent_metainfo, $save_path = '', $extra_options = array()) { - if(!empty($save_path)) $extra_options['savepath'] = $save_path; + if (!empty($save_path)) { + $extra_options['savepath'] = $save_path; + } $extra_options['torrents'] = $torrent_metainfo; #$extra_options['skip_checking'] = 'true'; //跳校验 // 关键 上传文件流 multipart/form-data【严格按照api文档编写】 $post_data = $this->buildData($extra_options); #p($post_data); // 设置请求头 - $this->curl->setHeader('Content-Type','multipart/form-data; boundary='.$this->delimiter); - $this->curl->setHeader('Content-Length',strlen($post_data)); + $this->curl->setHeader('Content-Type', 'multipart/form-data; boundary='.$this->delimiter); + $this->curl->setHeader('Content-Length', strlen($post_data)); return $this->postData('torrent_add', $post_data); } @@ -250,7 +255,8 @@ class qBittorrent * 拼接种子urls multipart/form-data * https://github.com/qbittorrent/qBittorrent/wiki/Web-API-Documentation#add-new-torrent */ - private function buildUrls($param){ + private function buildUrls($param) + { $this->delimiter = uniqid(); $eol = "\r\n"; $data = ''; @@ -267,7 +273,8 @@ class qBittorrent * 拼接种子上传文件流 multipart/form-data * https://github.com/qbittorrent/qBittorrent/wiki/Web-API-Documentation#add-new-torrent */ - private function buildData($param){ + private function buildData($param) + { $this->delimiter = uniqid(); $eol = "\r\n"; $data = ''; diff --git a/app/Class/uTorrent.php b/app/Class/uTorrent.php index 0f3412e..7be390a 100644 --- a/app/Class/uTorrent.php +++ b/app/Class/uTorrent.php @@ -29,7 +29,8 @@ define("UTORRENT_STATUS_STARTED", 1); define("UTORRENT_STATUS_CHECKED", 2); define("UTORRENT_STATUS_START_AFTER_CHECK", 4); -class uTorrent { +class uTorrent +{ // class static variables private static $base = "%s/gui/%s"; @@ -42,8 +43,9 @@ class uTorrent { protected $guid; // constructor - function __construct($host = "", $user = "", $pass = "") { - $this->host = rtrim($host,'/'); + public function __construct($host = "", $user = "", $pass = "") + { + $this->host = rtrim($host, '/'); $this->user = $user; $this->pass = $pass; @@ -54,7 +56,8 @@ class uTorrent { } // performs request - private function makeRequest($request, $decode = true, $options = array()) { + private function makeRequest($request, $decode = true, $options = array()) + { $request = preg_replace('/^\?/', '?token='.$this->token . '&', $request); $ch = curl_init(); @@ -71,12 +74,14 @@ class uTorrent { } // implodes given parameter with glue, whether it is an array or not - private function paramImplode($glue, $param) { + private function paramImplode($glue, $param) + { return $glue.implode($glue, is_array($param) ? $param : array($param)); } // gets token, returns true on success - private function getToken() { + private function getToken() + { $url = sprintf(self::$base, $this->host, 'token.html'); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); @@ -101,7 +106,8 @@ class uTorrent { } // returns the uTorrent build number - public function getBuild(){ + public function getBuild() + { $json = $this->makeRequest("?"); return $json['build']; } @@ -109,13 +115,15 @@ class uTorrent { // returns an array of files for the specified torrent hash // TODO: // - (when implemented in API) allow multiple hashes to be specified - public function getFiles($hash) { + public function getFiles($hash) + { $json = $this->makeRequest("?action=getfiles&hash=".$hash); return $json['files']; } // returns an array of all labels - public function getLabels(){ + public function getLabels() + { $json = $this->makeRequest("?list=1"); return $json['label']; } @@ -123,19 +131,22 @@ class uTorrent { // returns an array of the properties for the specified torrent hash // TODO: // - (when implemented in API) allow multiple hashes to be specified - public function getProperties($hash) { + public function getProperties($hash) + { $json = $this->makeRequest("?action=getprops&hash=".$hash); return $json['props']; } // returns an array of all settings - public function getSettings() { + public function getSettings() + { $json = $this->makeRequest("?action=getsettings"); return $json['settings']; } // returns an array of all torrent jobs and related information - public function getTorrents() { + public function getTorrents() + { $json = $this->makeRequest("?list=1"); return $json['torrents']; } @@ -144,7 +155,8 @@ class uTorrent { * Get all the RSS favourites/filters * @return model\Filter[] */ - public function getRSSFilters() { + public function getRSSFilters() + { $json = $this->makeRequest("?list=1"); $filters = array(); foreach ($json['rssfilters'] as $filter) { @@ -157,7 +169,8 @@ class uTorrent { * Update an RSS filter as retrieved from getRSSFilters * @param \uTorrent\model\Filter $filter */ - public function setRSSFilter(model\Filter $filter) { + public function setRSSFilter(model\Filter $filter) + { $request = array_merge(array('action' => 'filter-update'), $filter->toParams()); return $this->makeRequest('?'.http_build_query($request)); } @@ -168,7 +181,8 @@ class uTorrent { * @param \uTorrent\model\Filter $filter * @return int ID of the new filter */ - public function addRSSFilter(model\Filter $filter) { + public function addRSSFilter(model\Filter $filter) + { $filter->filterId = -1; $resp = $this->setRSSFilter($filter); if (!empty($resp['filter_ident'])) { @@ -179,77 +193,90 @@ class uTorrent { } // returns true if WebUI server is online and enabled, false otherwise - public function is_online() { + public function is_online() + { return is_array($this->makeRequest("?")); } // sets the properties for the specified torrent hash // TODO: // - allow multiple hashes, properties, and values to be set simultaneously - public function setProperties($hash, $property, $value) { + public function setProperties($hash, $property, $value) + { $this->makeRequest("?action=setprops&hash=".$hash."&s=".$property."&v=".$value, false); } // sets the priorities for the specified files in the specified torrent hash - public function setPriority($hash, $files, $priority) { + public function setPriority($hash, $files, $priority) + { $this->makeRequest("?action=setprio&hash=".$hash."&p=".$priority.$this->paramImplode("&f=", $files), false); } // sets the settings // TODO: // - allow multiple settings and values to be set simultaneously - public function setSetting($setting, $value) { + public function setSetting($setting, $value) + { $this->makeRequest("?action=setsetting&s=".$setting."&v=".$value, false); } // add a file to the list - public function torrentAdd($filename, &$estring = false) { + public function torrentAdd($filename, &$estring = false) + { $split = explode(":", $filename, 2); if (count($split) > 1 && (stristr("|http|https|file|magnet|", "|".$split[0]."|") !== false)) { $this->makeRequest("?action=add-url&s=".urlencode($filename), false); - } - elseif (file_exists($filename)) { + } elseif (file_exists($filename)) { $json = $this->makeRequest("?action=add-file", true, array(CURLOPT_POSTFIELDS => array("torrent_file" => "@".realpath($filename)))); if (isset($json['error'])) { - if ($estring !== false) $estring = $json['error']; + if ($estring !== false) { + $estring = $json['error']; + } return false; } return true; - } - else { - if ($estring !== false) $estring = "File doesn't exist!"; + } else { + if ($estring !== false) { + $estring = "File doesn't exist!"; + } return false; } } // force start the specified torrent hashes - public function torrentForceStart($hash) { + public function torrentForceStart($hash) + { $this->makeRequest("?action=forcestart".$this->paramImplode("&hash=", $hash), false); } // pause the specified torrent hashes - public function torrentPause($hash) { + public function torrentPause($hash) + { $this->makeRequest("?action=pause".$this->paramImplode("&hash=", $hash), false); } // recheck the specified torrent hashes - public function torrentRecheck($hash) { + public function torrentRecheck($hash) + { $this->makeRequest("?action=recheck".$this->paramImplode("&hash=", $hash), false); } // start the specified torrent hashes - public function torrentStart($hash) { + public function torrentStart($hash) + { $this->makeRequest("?action=start".$this->paramImplode("&hash=", $hash), false); } // stop the specified torrent hashes - public function torrentStop($hash) { + public function torrentStop($hash) + { $this->makeRequest("?action=stop".$this->paramImplode("&hash=", $hash), false); } // remove the specified torrent hashes (and data, if $data is set to true) - public function torrentRemove($hash, $data = false) { + public function torrentRemove($hash, $data = false) + { $this->makeRequest("?action=".($data ? "removedata" : "remove").$this->paramImplode("&hash=", $hash), false); } } diff --git a/app/config/config.sample.php b/app/config/config.sample.php index d7202c2..6b3b559 100644 --- a/app/config/config.sample.php +++ b/app/config/config.sample.php @@ -1,352 +1,352 @@ 'IYUU', - // 2.server酱 微信通知配置 - 'sc.ftqq.com' => '', - // 3.发布员鉴权 - 'secret' => '', - // 4.全局默认配置 + // 1.爱语飞飞 微信通知配置 + 'iyuu.cn' => 'IYUU', + // 2.server酱 微信通知配置 + 'sc.ftqq.com' => '', + // 3.发布员鉴权 + 'secret' => '', + // 4.全局默认配置 'default' => array( - // 5.【必须配置】浏览器UA,打开http://demo.iyuu.cn 复制过来即可 - 'userAgent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36', - // 6.【自动辅种必须配置】全局客户端设置(条目不够可以复制,用不到的请删除) + // 5.【必须配置】浏览器UA,打开http://demo.iyuu.cn 复制过来即可 + 'userAgent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36', + // 6.【自动辅种必须配置】全局客户端设置(条目不够可以复制,用不到的请删除) 'clients' => array( - // 全局客户端设置 开始 + // 全局客户端设置 开始 array( - 'type' => 'transmission', // 支持:transmission、qBittorrent - 'host' => 'http://127.0.0.1:9091/transmission/rpc', - 'username' => '', - 'password' => '', - //'move' =>array( - // 'type' => 2, // 0保持不变,1减,2加, 3直接替换 - // 'path' =>array( - // '/sda1' => '/volume1', - // ), - //), - ), - // (条目不够可以复制,用不到的请删除) - array( - 'type' => 'qBittorrent', // 支持:transmission、qBittorrent - 'host' => 'http://www.baidu.com:8083', - 'username' => '', - 'password' => '', - ), - // 全局客户端设置 结束 - ), - 'CONNECTTIMEOUT'=> 60, + 'type' => 'transmission', // 支持:transmission、qBittorrent + 'host' => 'http://127.0.0.1:9091/transmission/rpc', + 'username' => '', + 'password' => '', + //'move' =>array( + // 'type' => 2, // 0保持不变,1减,2加, 3直接替换 + // 'path' =>array( + // '/sda1' => '/volume1', + // ), + //), + ), + // (条目不够可以复制,用不到的请删除) + array( + 'type' => 'qBittorrent', // 支持:transmission、qBittorrent + 'host' => 'http://www.baidu.com:8083', + 'username' => '', + 'password' => '', + ), + // 全局客户端设置 结束 + ), + 'CONNECTTIMEOUT'=> 60, 'TIMEOUT' => 600, - ), - /** - * 以下为各站点的独立配置(互不影响、互不冲突) - * 自动辅种:需要配置各站的passkey(没有配置passkey的站点会自动跳过) - */ + ), + /** + * 以下为各站点的独立配置(互不影响、互不冲突) + * 自动辅种:需要配置各站的passkey(没有配置passkey的站点会自动跳过) + */ // m-team 序号:1 'm-team' => array( - // 14.m-team的cookie 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => 'tp=', - // 15.m-team的passkey 【必须配置】 - 'passkey' => '', - // 种子Tracker的IP地址选择 可选:ipv4,ipv6 - 'ip_type' => 'ipv4', + // 14.m-team的cookie 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => 'tp=', + // 15.m-team的passkey 【必须配置】 + 'passkey' => '', + // 种子Tracker的IP地址选择 可选:ipv4,ipv6 + 'ip_type' => 'ipv4', ), // keepfrds 序号:2 'keepfrds' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // ourbits 序号:3 - 'ourbits' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - 'id' => 0, // 用户ID - 'is_vip' => 0, // 是否具有VIP或特殊权限?0 普通,1 VIP + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // ourbits 序号:3 + 'ourbits' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + 'id' => 0, // 用户ID + 'is_vip' => 0, // 是否具有VIP或特殊权限?0 普通,1 VIP ), // HDSky 序号:4 'hdsky' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', ), - // pter 序号:5 - 'pter' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // pter 序号:5 + 'pter' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', ), - // tjupt 序号:6 - 'tjupt' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // tjupt 序号:6 + 'tjupt' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', ), - // hdhome 序号:7 - 'hdhome' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // hdhome 序号:7 + 'hdhome' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', ), - // btschool 序号:8 - 'btschool' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // btschool 序号:8 + 'btschool' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', - ), - // PTHome 序号:9 + ), + // PTHome 序号:9 'pthome' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', ), - // hddolby 序号:10 - 'hddolby' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // hddolby 序号:10 + 'hddolby' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', ), - // TorrentCCF 序号:11 + // TorrentCCF 序号:11 'torrentccf' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', ), - // PTMSG 序号:12 + // PTMSG 序号:12 'ptmsg' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', ), - // MoeCat 序号:13 + // MoeCat 序号:13 'moecat' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - // 种子Tracker的IP地址选择 可选:ipv4,ipv6 - 'ip_type' => 'ipv4', + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + // 种子Tracker的IP地址选择 可选:ipv4,ipv6 + 'ip_type' => 'ipv4', ), // totheglory 序号:14 'ttg' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', ), - // nanyangpt 序号:15 + // nanyangpt 序号:15 'nanyangpt' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', - ), - // springsunday.net 序号:16 + ), + // springsunday.net 序号:16 'ssd' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', - ), - // yingk 序号:17 + ), + // yingk 序号:17 'yingk' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', - ), - // hdcity 序号:18 + ), + // hdcity 序号:18 'hdcity' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 cuhash + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 cuhash 'passkey' => '', - ), - // 52pt.site 序号:19 + ), + // 52pt.site 序号:19 '52pt' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', - ), - // brobits.cc 序号:20 + ), + // brobits.cc 序号:20 'brobits' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', - ), - // www.beitai.pt 序号:21 + ), + // www.beitai.pt 序号:21 'beitai' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', - ), - // pt.eastgame.org 序号:22 + ), + // pt.eastgame.org 序号:22 'eastgame' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', - ), - // pt.soulvoice.club 序号:23 + ), + // pt.soulvoice.club 序号:23 'soulvoice' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', - ), - // chdbits 序号:24 + ), + // chdbits 序号:24 'chdbits' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 'passkey' => '', - ), - // leaguehd 序号:25 + ), + // leaguehd 序号:25 'leaguehd' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // ptsbao.club 序号:26 - 'ptsbao' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // hdchina 序号:27 - 'hdchina' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // hdarea 序号:28 - 'hdarea' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // hdtime 序号:29 - 'hdtime' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // 1ptba 序号:30 - '1ptba' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // hd4fans 序号:31 - 'hd4fans' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // hdbug 序号:32 - 'hdbug' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // opencd 序号:33 - 'opencd' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // hdstreet 序号:34 - 'hdstreet' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // joyhd 序号:35 - 'joyhd' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // dmhy 序号:36 - 'dmhy' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // upxin 序号:37 - 'upxin' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // oshen 序号:38 - 'oshen' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // discfan 序号:39 - 'discfan' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // hdzone 序号:40 - 'hdzone' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // cnscg 序号:41 - 'cnscg' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // nicept 序号:42 - 'nicept' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // ptsbao.club 序号:26 + 'ptsbao' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // hdchina 序号:27 + 'hdchina' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // hdarea 序号:28 + 'hdarea' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // hdtime 序号:29 + 'hdtime' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // 1ptba 序号:30 + '1ptba' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // hd4fans 序号:31 + 'hd4fans' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // hdbug 序号:32 + 'hdbug' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // opencd 序号:33 + 'opencd' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // hdstreet 序号:34 + 'hdstreet' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // joyhd 序号:35 + 'joyhd' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // dmhy 序号:36 + 'dmhy' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // upxin 序号:37 + 'upxin' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // oshen 序号:38 + 'oshen' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // discfan 序号:39 + 'discfan' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // hdzone 序号:40 + 'hdzone' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // cnscg 序号:41 + 'cnscg' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // nicept 序号:42 + 'nicept' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), - // 配置文件结束 -); \ No newline at end of file + // 配置文件结束 +);