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.
 
 
 
IYUUAutoReseed/app/Class/Rpc.php

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;
}
}