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