diff --git a/.gitignore b/.gitignore index df534e3..2f6beec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ /app/torrent -/app/config/config.php +/config/config.php /php-7.2.12-nts /*.bat /*.sh diff --git a/app/config/config.sample.php b/app/config/config.sample.php deleted file mode 100644 index 334012d..0000000 --- a/app/config/config.sample.php +++ /dev/null @@ -1,362 +0,0 @@ - '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.【自动辅种必须配置】全局客户端设置(条目不够可以复制) - 'clients' => array( - // 全局客户端设置 开始 - # 开始 - array( - 'type' => 'transmission', // 支持:transmission、qBittorrent - 'host' => 'http://127.0.0.1:9091/transmission/rpc', // 警告!注意:transmission/rpc这段别动,你只需要修改 127.0.0.1:9091 - 'username' => '', - 'password' => '', - ), - # 结束 - # 开始 - array( - 'type' => 'qBittorrent', // 支持:transmission、qBittorrent - 'host' => 'http://www.baidu.com:8083', - 'username' => '', - 'password' => '', - ), - # 结束 - // 全局客户端设置 结束 - ), - 'move' =>array( - 'type' => 2, // 0保持不变,1减,2加, 3直接替换 - 'path' =>array( - '/sda1' => '/volume1', - ), - ), - 'CONNECTTIMEOUT'=> 60, - 'TIMEOUT' => 600, - ), - /** - * 以下为各站点的独立配置(互不影响、互不冲突) - * 自动辅种:需要配置各站的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', - ), - // keepfrds 序号:2 - 'keepfrds' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // ourbits 序号:3 - 'ourbits' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - 'id' => 0, // 用户ID - 'is_vip' => 0, // 是否具有VIP或特殊权限?0 普通,1 VIP - ), - // HDSky 序号:4 - 'hdsky' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // pter 序号:5 - 'pter' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // tjupt 序号:6 - 'tjupt' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // hdhome 序号:7 - 'hdhome' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // btschool 序号:8 - 'btschool' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // PTHome 序号:9 - 'pthome' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // hddolby 序号:10 - 'hddolby' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // TorrentCCF 序号:11 - 'torrentccf' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // PTMSG 序号:12 - 'ptmsg' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // MoeCat 序号:13 - 'moecat' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - // 种子Tracker的IP地址选择 可选:ipv4,ipv6 - 'ip_type' => 'ipv4', - ), - // totheglory 序号:14 - 'ttg' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // nanyangpt 序号:15 - 'nanyangpt' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // springsunday.net 序号:16 - 'ssd' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // yingk 序号:17 - 'yingk' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // hdcity 序号:18 - 'hdcity' => array( - // 必须配置 - 'cookie' => '', - // 如果需要自动辅种,必须配置cuhash - 'passkey' => '', - ), - // 52pt.site 序号:19 - '52pt' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // brobits.cc 序号:20 - 'brobits' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // www.beitai.pt 序号:21 - 'beitai' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // pt.eastgame.org 序号:22 - 'eastgame' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // pt.soulvoice.club 序号:23 - 'soulvoice' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // chdbits 序号:24 - 'chdbits' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - // 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' => '', - ), - // hdbd 序号:43 伊甸园 - 'hdbd' => array( - // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) - 'cookie' => '', - // 如果需要自动辅种,必须配置 - 'passkey' => '', - ), - - // 配置文件结束 -); \ No newline at end of file diff --git a/app/iyuu.cn.php b/app/iyuu.cn.php new file mode 100644 index 0000000..518f4a6 --- /dev/null +++ b/app/iyuu.cn.php @@ -0,0 +1,631 @@ + '/api/add', + 'update' => '/api/update', + 'reseed' => '/api/reseed', + 'login' => '/login', + ); + /** + * 退出状态码 + * @var int + */ + public static $ExitCode = 0; + /** + * 客户端转移做种 状态码[请把transmission配置为第一个客户端] + * @var array + */ + public static $move = null; + /** + * 微信消息体 + * @var array + */ + public static $wechatMsg = array( + 'hashCount' => 0, // 提交给服务器的hash总数 + 'sitesCount' => 0, // 可辅种站点总数 + 'reseedCount' => 0, // 返回的总数据 + 'reseedSuccess' => 0, // 成功:辅种成功(会加入缓存,哪怕种子在校验中,下次也会过滤) + 'reseedError' => 0, // 错误:辅种失败(可以重试) + 'reseedRepeat' => 0, // 重复:客户端已做种 + 'reseedSkip' => 0, // 跳过:因未设置passkey,而跳过 + 'reseedPass' => 0, // 忽略:因上次成功添加、存在缓存,而跳过 + ); + /** + * 初始化 + * @return void + */ + public static function init() + { + global $configALL; + self::$clients = isset($configALL['default']['clients']) && $configALL['default']['clients'] ? $configALL['default']['clients'] : array(); + echo "程序正在初始化运行参数... \n"; + // 递归删除上次历史记录 + IFile::rmdir(self::$cacheDir, true); + // 建立目录 + IFile::mkdir(self::$cacheDir); + IFile::mkdir(self::$cacheHash); + // 连接全局客户端 + self::links(); + // 合作站点自动注册鉴权 + Oauth::login(self::$apiUrl . self::$endpoints['login']); + } + /** + * 连接远端RPC服务器 + * + * @param string + * @return bool + */ + public static function links() + { + if (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; + default: + echo '[ERROR] '.$v['type']; + exit(1); + break; + } + self::$links[$k]['type'] = $v['type']; + // 检查是否转移种子的做种客户端? + if (isset($v['move']) && $v['move']) { + self::$move = array($k,$v['type']); + } + } catch (Exception $e) { + echo '[ERROR] ' . $e->getMessage() . PHP_EOL; + exit(1); + } + } + } + return true; + } + /** + * 从客户端获取种子的哈希列表 + * @var array + */ + public static function get() + { + $hashArray = array(); + foreach (self::$clients as $k => $v) { + $result = array(); + $res = $info_hash = array(); + $json = $sha1 = ''; + try { + switch ($v['type']) { + case 'transmission': + $ids = $fields = array(); + #$fields = array( "id", "status", "name", "hashString", "downloadDir", "torrentFile" ); + $fields = array( "id", "status", "hashString", "downloadDir"); + $result = self::$links[$k]['rpc']->get($ids, $fields); + if (empty($result->result) || $result->result != 'success') { + // 获取种子列表 失败 + echo "获取种子列表失败,原因可能是transmission暂时无响应,请稍后重试! \n"; + break; + } + if (empty($result->arguments)) { + echo "未获取到需要辅种的数据,请多多保种,然后重试! \n"; + break; + } + // 对象转数组 + $res = object_array($result->arguments->torrents); + // 过滤,只保留正常做种 + $res = array_filter($res, "filterStatus"); + // 提取数组:hashString + $info_hash = array_column($res, 'hashString'); + // 升序排序 + sort($info_hash); + // 微信模板消息 统计 + self::$wechatMsg['hashCount'] += count($info_hash); + $json = json_encode($info_hash, JSON_UNESCAPED_UNICODE); + // 去重 应该从文件读入,防止重复提交 + $sha1 = sha1($json); + if (isset($hashArray['sha1']) && (in_array($sha1, $hashArray['sha1']) != false)) { + break; + } + // 组装返回数据 + $hashArray['hash']['clients_'.$k] = $json; + $hashArray['sha1'][] = $sha1; + // 变换数组:hashString为键 + self::$links[$k]['hash'] = array_column($res, "downloadDir", 'hashString'); + #p(self::$links[$k]['hash']);exit; + break; + case 'qBittorrent': + $result = self::$links[$k]['rpc']->torrentList(); + $res = json_decode($result, true); + if (empty($res)) { + echo "未获取到需要辅种的数据,请多多保种,然后重试! \n"; + break; + } + #p($res);exit; + // 过滤,只保留正常做种 + $res = array_filter($res, "qbfilterStatus"); + // 提取数组:hashString + $info_hash = array_column($res, 'hash'); + // 升序排序 + sort($info_hash); + // 微信模板消息 统计 + self::$wechatMsg['hashCount'] += count($info_hash); + $json = json_encode($info_hash, JSON_UNESCAPED_UNICODE); + // 去重 应该从文件读入,防止重复提交 + $sha1 = sha1($json); + if (isset($hashArray['sha1']) && (in_array($sha1, $hashArray['sha1']) != false)) { + break; + } + // 组装返回数据 + $hashArray['hash']['clients_'.$k] = $json; + $hashArray['sha1'][] = $sha1; + // 变换数组:hash为键 + self::$links[$k]['hash'] = array_column($res, "save_path", 'hash'); + #p(self::$links[$k]['hash']);exit; + break; + default: + echo '[ERROR] '.$v['type']; + exit(1); + break; + } + // 是否执行转移种子做种客户端? + if (self::$move != null && (empty($v['move']))) { + self::move($res, $v['type']); + } + } catch (Exception $e) { + echo '[ERROR] ' . $e->getMessage() . PHP_EOL; + exit(1); + } + } + return $hashArray; + } + /** + * @brief 添加下载任务 + * @param string $torrent 种子元数据 + * @param string $save_path 保存路径 + * @return bool + */ + public static function add($rpcKey, $torrent, $save_path = '', $extra_options = array()) + { + try { + $is_url = false; + if ((strpos($torrent, 'http://')===0) || (strpos($torrent, 'https://')===0) || (strpos($torrent, 'magnet:?xt=urn:btih:')===0)) { + $is_url = true; + } + // 下载服务器类型 + $type = self::$links[$rpcKey]['type']; + // 判断 + switch ($type) { + case 'transmission': + $extra_options['paused'] = true; + if ($is_url) { + $result = self::$links[$rpcKey]['rpc']->add($torrent, $save_path, $extra_options); // 种子URL添加下载任务 + } else { + $result = self::$links[$rpcKey]['rpc']->add_metainfo($torrent, $save_path, $extra_options); // 种子元数据添加下载任务 + } + if (isset($result->result) && $result->result == 'success') { + $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; + } + print "********RPC添加下载任务成功 [{$result->result}] (id=$id) \n"; + if ($is_url) { + print "种子:".$torrent. "\n"; + } + print "名字:".$name."\n\n"; + return true; + } else { + $errmsg = isset($result->result) ? $result->result : '未知错误,请稍后重试!'; + print "-----RPC添加种子任务,失败 [{$errmsg}] \n"; + if ($is_url) { + print "种子:".$torrent. "\n"; + } + } + break; + case 'qBittorrent': + $extra_options['paused'] = 'true'; + $extra_options['autoTMM'] = 'false'; //关闭自动种子管理 + if ($is_url) { + $result = self::$links[$rpcKey]['rpc']->add($torrent, $save_path, $extra_options); // 种子URL添加下载任务 + } else { + $extra_options['name'] = 'torrents'; + $extra_options['filename'] = rand(1, 4294967200).'.torrent'; + $result = self::$links[$rpcKey]['rpc']->add_metainfo($torrent, $save_path, $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) { + echo '[ERROR] ' . $e->getMessage() . PHP_EOL; + } + return false; + } + + /** + * 正常做种的种子在各下载器的互相转移 + */ + public static function move($torrent=array(), $type = 'qBittorrent') + { + switch ($type) { + case 'transmission': + break; + case 'qBittorrent': + foreach ($torrent as $k => $v) { + // 路径转换 + #$v['save_path'] = '/volume3' . $v['save_path']; // docker路径转换 + self::add(self::$move[0], $v['magnet_uri'], $v['save_path']); + } + break; + default: + echo '[ERROR] '.$type; + break; + } + } + /** + * @brief 提交种子hash给远端API,用来获取辅种数据 + * @param array $hashArray 种子hash数组 + * @return + */ + public static function call($hashArray = array()) + { + global $configALL; + $resArray = $sites = array(); + $curl = new Curl(); + $curl->setOpt(CURLOPT_SSL_VERIFYPEER, false); + // 签名 + $hashArray['timestamp'] = time(); + // 爱语飞飞token + $hashArray['sign'] = Oauth::getSign(); + $hashArray['version'] = self::VER; + // 写日志 + if (true) { + // 文件句柄 + $resource = fopen(self::$cacheDir.'hashString.txt', "wb"); + // 成功:返回写入字节数,失败返回false + $worldsnum = fwrite($resource, p($hashArray, false)); + fclose($resource); + } + // 发起请求 + echo "正在提交辅种信息…… \n"; + $res = $curl->post(self::$apiUrl . self::$endpoints['reseed'], $hashArray); + $resArray = json_decode($res->response, true); + // 写日志 + if (true) { + // 文件句柄 + $resource = fopen(self::$cacheDir.'reseed.txt', "wb"); + // 成功:返回写入字节数,失败返回false + $worldsnum = fwrite($resource, p($resArray, false)); + fclose($resource); + } + // 判断返回值 + if (isset($resArray['errmsg']) && ($resArray['errmsg'] == 'ok')) { + echo "辅种信息提交成功!!! \n\n"; + } else { + $errmsg = isset($resArray['errmsg']) ? $resArray['errmsg'] : '远端服务器无响应,请稍后重试!'; + echo '-----辅种失败,原因:' .$errmsg. " \n\n"; + exit(1); + } + // 可辅种站点信息列表 + $sites = $resArray['sites']; + self::$wechatMsg['sitesCount'] = count($sites); + #p($sites); + // 按客户端循环辅种 开始 + foreach (self::$links as $k => $v) { + $reseed = $infohash_Dir = array(); + // info_hash 对应的下载目录 + $infohash_Dir = self::$links[$k]['hash']; + if (empty($resArray['clients_'.$k])) { + echo "clients_".$k."没有查询到可辅种数据 \n\n"; + continue; + } + #p($infohash_Dir); + // 当前客户端辅种数据 + $reseed = $resArray['clients_'.$k]; + foreach ($reseed as $info_hash => $vv) { + // 当前种子哈希对应的目录 + $downloadDir = $infohash_Dir[$info_hash]; + foreach ($vv['torrent'] as $id => $value) { + // 匹配的辅种数据累加 + self::$wechatMsg['reseedCount']++; + // 站点id + $sitesID = $value['sid']; + $url = $_url = ''; + $download_page = $details_url = ''; + // 页面规则 + $download_page = str_replace('{}', $value['torrent_id'], $sites[$sitesID]['download_page']); + $_url = 'https://' .$sites[$sitesID]['base_url']. '/' .$download_page; + if (empty($configALL[$sites[$sitesID]['site']]['passkey'])) { + echo '-------因当前' .$sites[$sitesID]['site']. '站点未设置passkey,已跳过!!' . "\n\n"; + self::$wechatMsg['reseedSkip']++; + continue; + } + // 种子URL组合方式区分 + switch ($sites[$sitesID]['site']) { + case 'ttg': + $url = $_url."/". $configALL[$sites[$sitesID]['site']]['passkey']; + break; + case 'm-team': + $ip_type = ''; + if (isset($configALL[$sites[$sitesID]['site']]['ip_type'])) { + $ip_type = $configALL[$sites[$sitesID]['site']]['ip_type'] == 'ipv6' ? '&ipv6=1' : ''; + } + $url = $_url."&passkey=". $configALL[$sites[$sitesID]['site']]['passkey'] . $ip_type. "&https=1"; + break; + case 'moecat': + $ip_type = ''; + if (isset($configALL[$sites[$sitesID]['site']]['ip_type'])) { + $ip_type = $configALL[$sites[$sitesID]['site']]['ip_type'] == 'ipv6' ? '&ipv6=1' : ''; + } + $url = $_url."&passkey=". $configALL[$sites[$sitesID]['site']]['passkey'] . $ip_type. "&https=1"; + break; + default: + $url = $_url."&passkey=". $configALL[$sites[$sitesID]['site']]['passkey']; + break; + } + /** + * 检查站点是否可以辅种 + */ + // 判断是否具有VIP或特殊权限? + $is_vip = isset($configALL[$sites[$sitesID]['site']]['is_vip']) && $configALL[$sites[$sitesID]['site']]['is_vip'] ? 1 : 0; + if ((in_array($sites[$sitesID]['site'], self::$noReseed)==false) || $is_vip) { + /** + * 可以辅种 + */ + if (isset($infohash_Dir[$value['info_hash']])) { + // 与客户端现有种子重复 + echo '-------与客户端现有种子重复:'.$_url."\n\n"; + self::$wechatMsg['reseedRepeat']++; + continue; + } else { + // 判断上次是否成功添加? + if (is_file(self::$cacheHash . $value['info_hash'].'.txt')) { + echo '-------当前种子上次辅种已成功添加,已跳过!'.$_url."\n\n"; + self::$wechatMsg['reseedPass']++; + continue; + } + // 种子元数据获取 + switch ($sites[$sitesID]['site']) { + case 'hdchina': + if (empty($configALL[$sites[$sitesID]['site']]['cookie'])) { + echo '-------因当前' .$sites[$sitesID]['site']. '站点未设置cookie,已跳过!!' . "\n\n"; + self::$wechatMsg['reseedSkip']++; + break; + } + if (isset($configALL[$sites[$sitesID]['site']]['limit'])) { + echo "当前站点触发人机验证,已加入排除列表 \n"; + } + $cookie = isset($configALL[$sites[$sitesID]['site']]['cookie']) ? $configALL[$sites[$sitesID]['site']]['cookie'] : ''; + $userAgent = $configALL['default']['userAgent']; + // 拼接URL + $details_page = str_replace('{}', $value['torrent_id'], 'details.php?id={}&hit=1'); + $details_url = 'https://' .$sites[$sitesID]['base_url']. '/' .$details_page; + $details_html = download($details_url, $cookie, $userAgent); + print "种子详情页:".$details_url. "\n"; + // 提取种子下载地址 + $download_page = str_replace('{}', '', $sites[$sitesID]['download_page']); + $offset = strpos($details_html, $download_page); + $urlTemp = substr($details_html, $offset, 50); + // 种子地址 + $_url = substr($urlTemp, 0, strpos($urlTemp, '">')); + $_url = 'https://' .$sites[$sitesID]['base_url']. '/' . $_url; + print "种子下载页:".$_url. "\n"; + $url = download($_url, $cookie, $userAgent); + if (strpos($url, '系统检测到过多的种子下载请求') != false) { + echo "触发人机验证 \n"; + ff($sites[$sitesID]['site']. ' 触发人机验证,请重新设置!'); + self::$noReseed[] = 'hdchina'; + $configALL[$sites[$sitesID]['site']]['limit'] = 1; + } + break; + case 'hdcity': + if (empty($configALL[$sites[$sitesID]['site']]['cookie'])) { + echo '-------因当前' .$sites[$sitesID]['site']. '站点未设置cookie,已跳过!!' . "\n\n"; + self::$wechatMsg['reseedSkip']++; + break; + } + $cookie = isset($configALL[$sites[$sitesID]['site']]['cookie']) ? $configALL[$sites[$sitesID]['site']]['cookie'] : ''; + $userAgent = $configALL['default']['userAgent']; + print "种子:".$_url. "\n"; + if (isset($configALL[$sites[$sitesID]['site']]['cuhash'])) { + // 已获取cuhash + # code... + } else { + // 获取cuhash + $html = download('https://' .$sites[$sitesID]['base_url']. '/pt', $cookie, $userAgent); + // 提取种子下载地址 + $offset = strpos($html, 'cuhash='); + $len = strlen('cuhash='); + $cuhashTemp = substr($html, $offset+$len, 40); + $configALL[$sites[$sitesID]['site']]['cuhash'] = substr($cuhashTemp, 0, strpos($cuhashTemp, '"')); + } + $url = $_url."&cuhash=". $configALL[$sites[$sitesID]['site']]['cuhash']; + // 城市下载种子时会302转向 + $url = download($url, $cookie, $userAgent); + break; + default: + break; + } + // 把拼接的种子URL,推送给下载器 + $ret = false; + // 成功返回:true + $ret = self::add($k, $url, $downloadDir); + // 添加成功的种子,以infohash为文件名,写入缓存 + if ($ret) { + // 成功的种子 + // 文件句柄 + $resource = fopen(self::$cacheHash . $value['info_hash'].'.txt', "wb"); + // 成功:返回写入字节数,失败返回false + $worldsnum = fwrite($resource, $url); + fclose($resource); + self::$wechatMsg['reseedSuccess']++; + continue; + } else { + // 失败的种子 + // 站点类型判断 + switch ($sites[$sitesID]['site']) { + case 'hdcity': + echo '当前' .$sites[$sitesID]['site']. '站点是配置cuhash(不是passkey),添加成功说明配置正确!如果添加任务失败,请查阅常见问题!!' . "\n"; + break; + default: + break; + } + // 失败累加 + self::$wechatMsg['reseedError']++; + continue; + } + } + } else { + /** + * 不辅种 + */ + echo '-------已跳过不辅种的站点:'.$_url."\n\n"; + // 写入日志文件,供用户手动辅种 + if (!isset($infohash_Dir[$value['info_hash']])) { + // 站点类型判断 + switch ($sites[$sitesID]['site']) { + case 'hdchina': + $url = $_url; + break; + default: + break; + } + // 文件句柄 + $resource = fopen(self::$cacheDir . $sites[$sitesID]['site'].'.txt', 'a'); + // 成功:返回写入字节数,失败返回false + $worldsnum = fwrite($resource, 'clients_'.$k."\n".$downloadDir."\n".$url."\n".$details_url."\n\n"); + fclose($resource); + } + } + } + } + } + // 按客户端循环辅种 结束 + } + /** + * + */ + public static function wechatMessage() + { + $br = "\r\n"; + $text = 'IYUU自动辅种-统计报表'; + $desp = '总做种:'.self::$wechatMsg['hashCount'] . ' [客户端正在做种的hash总数]' .$br; + $desp .= '返回数据:'.self::$wechatMsg['reseedCount']. ' [服务器返回的可辅种数据]' .$br; + $desp .= '支持站点:'.self::$wechatMsg['sitesCount']. ' [当前支持自动辅种的站点数量]' .$br; + $desp .= '成功:'.self::$wechatMsg['reseedSuccess']. ' [辅种成功,会把hash加入缓存]' .$br; + $desp .= '失败:'.self::$wechatMsg['reseedError']. ' [下载器下载种子失败或网络超时引起,可以重试]' .$br; + $desp .= '重复:'.self::$wechatMsg['reseedRepeat']. ' [客户端已做种]' .$br; + $desp .= '跳过:'.self::$wechatMsg['reseedSkip']. ' [未设置passkey]' .$br; + $desp .= '忽略:'.self::$wechatMsg['reseedPass']. ' [成功添加存在缓存]' .$br; + return ff($text, $desp); + } +} + +/** + * transmission过滤函数,只保留正常做种 + */ +function filterStatus($v) +{ + return isset($v['status']) && $v['status']===6; +} + +/** + * qBittorrent过滤函数,只保留正常做种 + */ +function qbfilterStatus($v) +{ + if (isset($v['state']) && in_array($v['state'], array('uploading','stalledUP','pausedUP','queuedUP','checkingUP','forcedUP'))) { + return true; + } + return false; +} +//PHP stdClass Object转array +function object_array($array) +{ + if (is_object($array)) { + $array = (array)$array; + } + if (is_array($array)) { + foreach ($array as $key=>$value) { + $array[$key] = object_array($value); + } + } + return $array; +} +// 对象转数组 +function object2array(&$object) +{ + return json_decode(json_encode($object), true); +} diff --git a/config/config.sample.php b/config/config.sample.php new file mode 100644 index 0000000..456d437 --- /dev/null +++ b/config/config.sample.php @@ -0,0 +1,362 @@ + '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.【自动辅种必须配置】全局客户端设置(条目不够可以复制) + 'clients' => array( + // 全局客户端设置 开始 + # 开始 + array( + 'type' => 'transmission', // 支持:transmission、qBittorrent + 'host' => 'http://127.0.0.1:9091/transmission/rpc', // 警告!注意:transmission/rpc这段别动,你只需要修改 127.0.0.1:9091 + 'username' => '', + 'password' => '', + ), + # 结束 + # 开始 + array( + 'type' => 'qBittorrent', // 支持:transmission、qBittorrent + 'host' => 'http://www.baidu.com:8083', + 'username' => '', + 'password' => '', + ), + # 结束 + // 全局客户端设置 结束 + ), + 'move' =>array( + 'type' => 2, // 0保持不变,1减,2加, 3直接替换 + 'path' =>array( + '/sda1' => '/volume1', + ), + ), + 'CONNECTTIMEOUT'=> 60, + 'TIMEOUT' => 600, + ), + /** + * 以下为各站点的独立配置(互不影响、互不冲突) + * 自动辅种:需要配置各站的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', + ), + // keepfrds 序号:2 + 'keepfrds' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // ourbits 序号:3 + 'ourbits' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + 'id' => 0, // 用户ID + 'is_vip' => 0, // 是否具有VIP或特殊权限?0 普通,1 VIP + ), + // HDSky 序号:4 + 'hdsky' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // pter 序号:5 + 'pter' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // tjupt 序号:6 + 'tjupt' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // hdhome 序号:7 + 'hdhome' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // btschool 序号:8 + 'btschool' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // PTHome 序号:9 + 'pthome' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // hddolby 序号:10 + 'hddolby' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // TorrentCCF 序号:11 + 'torrentccf' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // PTMSG 序号:12 + 'ptmsg' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // MoeCat 序号:13 + 'moecat' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + // 种子Tracker的IP地址选择 可选:ipv4,ipv6 + 'ip_type' => 'ipv4', + ), + // totheglory 序号:14 + 'ttg' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // nanyangpt 序号:15 + 'nanyangpt' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // springsunday.net 序号:16 + 'ssd' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // yingk 序号:17 + 'yingk' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // hdcity 序号:18 + 'hdcity' => array( + // 必须配置 + 'cookie' => '', + // 如果需要自动辅种,必须配置cuhash + 'passkey' => '', + ), + // 52pt.site 序号:19 + '52pt' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // brobits.cc 序号:20 + 'brobits' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // www.beitai.pt 序号:21 + 'beitai' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // pt.eastgame.org 序号:22 + 'eastgame' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // pt.soulvoice.club 序号:23 + 'soulvoice' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // chdbits 序号:24 + 'chdbits' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + // 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' => '', + ), + // hdbd 序号:43 伊甸园 + 'hdbd' => array( + // 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) + 'cookie' => '', + // 如果需要自动辅种,必须配置 + 'passkey' => '', + ), + + // 配置文件结束 +); diff --git a/app/config/version.php b/config/version.php similarity index 100% rename from app/config/version.php rename to config/version.php diff --git a/app/init.php b/init.php similarity index 63% rename from app/init.php rename to init.php index ad5662c..f872361 100644 --- a/app/init.php +++ b/init.php @@ -3,26 +3,23 @@ // 公共入口文件 //---------------------------------- // 定义目录 -defined('ROOT_PATH') or define("ROOT_PATH", dirname(__DIR__)); -defined('APP_PATH') or define('APP_PATH', __DIR__); +defined('ROOT_PATH') or define("ROOT_PATH", __DIR__); define('DS', DIRECTORY_SEPARATOR); define('TORRENT_PATH', APP_PATH.DS.'torrent'.DS); // 严格开发模式 -error_reporting( E_ALL ); +error_reporting(E_ALL); #ini_set('display_errors', 1); // 永不超时 ini_set('max_execution_time', 0); set_time_limit(0); // 内存限制,如果外面设置的内存比 /etc/php/php-cli.ini 大,就不要设置了 -if (intval(ini_get("memory_limit")) < 1024) -{ +if (intval(ini_get("memory_limit")) < 1024) { ini_set('memory_limit', '1024M'); } -if( PHP_SAPI != 'cli' ) -{ +if (PHP_SAPI != 'cli') { exit("You must run the CLI environment\n"); } @@ -30,13 +27,12 @@ if( PHP_SAPI != 'cli' ) date_default_timezone_set('Asia/Shanghai'); // 系统配置 -if( file_exists( APP_PATH."/config/config.php" ) ) -{ +if (file_exists(ROOT_PATH."/config/config.php")) { // 配置(全局变量) - $configALL = require_once APP_PATH."/config/config.php"; -}else{ + $configALL = require_once ROOT_PATH . "/config/config.php"; +} else { // 示例配置 - $configALL = require_once APP_PATH . '/config/config.sample.php'; + $configALL = require_once ROOT_PATH . '/config/config.sample.php'; } require_once ROOT_PATH . '/vendor/autoload.php'; diff --git a/iyuu.cn.php b/iyuu.cn.php deleted file mode 100644 index afa54d0..0000000 --- a/iyuu.cn.php +++ /dev/null @@ -1,626 +0,0 @@ - '/api/add', - 'update' => '/api/update', - 'reseed' => '/api/reseed', - 'login' => '/login', - ); - /** - * 退出状态码 - * @var int - */ - public static $ExitCode = 0; - /** - * 客户端转移做种 状态码[请把transmission配置为第一个客户端] - * @var array - */ - public static $move = null; - /** - * 微信消息体 - * @var array - */ - public static $wechatMsg = array( - 'hashCount' => 0, // 提交给服务器的hash总数 - 'sitesCount' => 0, // 可辅种站点总数 - 'reseedCount' => 0, // 返回的总数据 - 'reseedSuccess' => 0, // 成功:辅种成功(会加入缓存,哪怕种子在校验中,下次也会过滤) - 'reseedError' => 0, // 错误:辅种失败(可以重试) - 'reseedRepeat' => 0, // 重复:客户端已做种 - 'reseedSkip' => 0, // 跳过:因未设置passkey,而跳过 - 'reseedPass' => 0, // 忽略:因上次成功添加、存在缓存,而跳过 - ); - /** - * 初始化 - * @return void - */ - public static function init(){ - global $configALL; - self::$clients = isset($configALL['default']['clients']) && $configALL['default']['clients'] ? $configALL['default']['clients'] : array(); - echo "程序正在初始化运行参数... \n"; - // 递归删除上次历史记录 - IFile::rmdir(self::$cacheDir, true); - // 建立目录 - IFile::mkdir(self::$cacheDir); - IFile::mkdir(self::$cacheHash); - // 连接全局客户端 - self::links(); - // 合作站点自动注册鉴权 - Oauth::login(self::$apiUrl . self::$endpoints['login']); - } - /** - * 连接远端RPC服务器 - * - * @param string - * @return bool - */ - public static function links() - { - if(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; - default: - echo '[ERROR] '.$v['type']; - exit(1); - break; - } - self::$links[$k]['type'] = $v['type']; - // 检查是否转移种子的做种客户端? - if ( isset($v['move']) && $v['move'] ) { - self::$move = array($k,$v['type']); - } - } catch (Exception $e) { - echo '[ERROR] ' . $e->getMessage() . PHP_EOL; - exit(1); - } - } - } - return true; - } - /** - * 从客户端获取种子的哈希列表 - * @var array - */ - public static function get(){ - $hashArray = array(); - foreach ( self::$clients as $k => $v ){ - $result = array(); - $res = $info_hash = array(); - $json = $sha1 = ''; - try - { - switch($v['type']){ - case 'transmission': - $ids = $fields = array(); - #$fields = array( "id", "status", "name", "hashString", "downloadDir", "torrentFile" ); - $fields = array( "id", "status", "hashString", "downloadDir"); - $result = self::$links[$k]['rpc']->get($ids, $fields); - if ( empty($result->result) || $result->result != 'success' ){ - // 获取种子列表 失败 - echo "获取种子列表失败,原因可能是transmission暂时无响应,请稍后重试! \n"; - break; - } - if( empty($result->arguments) ){ - echo "未获取到需要辅种的数据,请多多保种,然后重试! \n"; - break; - } - // 对象转数组 - $res = object_array($result->arguments->torrents); - // 过滤,只保留正常做种 - $res = array_filter($res, "filterStatus"); - // 提取数组:hashString - $info_hash = array_column($res, 'hashString'); - // 升序排序 - sort($info_hash); - // 微信模板消息 统计 - self::$wechatMsg['hashCount'] += count($info_hash); - $json = json_encode($info_hash, JSON_UNESCAPED_UNICODE); - // 去重 应该从文件读入,防止重复提交 - $sha1 = sha1( $json ); - if ( isset($hashArray['sha1']) && (in_array($sha1, $hashArray['sha1']) != false) ) { - break; - } - // 组装返回数据 - $hashArray['hash']['clients_'.$k] = $json; - $hashArray['sha1'][] = $sha1; - // 变换数组:hashString为键 - self::$links[$k]['hash'] = array_column($res, "downloadDir", 'hashString'); - #p(self::$links[$k]['hash']);exit; - break; - case 'qBittorrent': - $result = self::$links[$k]['rpc']->torrentList(); - $res = json_decode($result,true); - if ( empty($res) ) { - echo "未获取到需要辅种的数据,请多多保种,然后重试! \n"; - break; - } - #p($res);exit; - // 过滤,只保留正常做种 - $res = array_filter($res, "qbfilterStatus"); - // 提取数组:hashString - $info_hash = array_column($res, 'hash'); - // 升序排序 - sort($info_hash); - // 微信模板消息 统计 - self::$wechatMsg['hashCount'] += count($info_hash); - $json = json_encode($info_hash, JSON_UNESCAPED_UNICODE); - // 去重 应该从文件读入,防止重复提交 - $sha1 = sha1( $json ); - if ( isset($hashArray['sha1']) && (in_array($sha1, $hashArray['sha1']) != false) ) { - break; - } - // 组装返回数据 - $hashArray['hash']['clients_'.$k] = $json; - $hashArray['sha1'][] = $sha1; - // 变换数组:hash为键 - self::$links[$k]['hash'] = array_column($res, "save_path", 'hash'); - #p(self::$links[$k]['hash']);exit; - break; - default: - echo '[ERROR] '.$v['type']; - exit(1); - break; - } - // 是否执行转移种子做种客户端? - if ( self::$move != null && (empty($v['move'])) ) { - self::move($res, $v['type']); - } - } catch (Exception $e) { - echo '[ERROR] ' . $e->getMessage() . PHP_EOL; - exit(1); - } - } - return $hashArray; - } - /** - * @brief 添加下载任务 - * @param string $torrent 种子元数据 - * @param string $save_path 保存路径 - * @return bool - */ - public static function add($rpcKey, $torrent, $save_path = '', $extra_options = array()) - { - try - { - $is_url = false; - if( (strpos($torrent,'http://')===0) || (strpos($torrent,'https://')===0) || (strpos($torrent,'magnet:?xt=urn:btih:')===0) ){ - $is_url = true; - } - // 下载服务器类型 - $type = self::$links[$rpcKey]['type']; - // 判断 - switch( $type ){ - case 'transmission': - $extra_options['paused'] = true; - if( $is_url ){ - $result = self::$links[$rpcKey]['rpc']->add( $torrent, $save_path, $extra_options ); // 种子URL添加下载任务 - } else{ - $result = self::$links[$rpcKey]['rpc']->add_metainfo( $torrent, $save_path, $extra_options ); // 种子元数据添加下载任务 - } - if(isset($result->result) && $result->result == 'success'){ - $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; - } - print "********RPC添加下载任务成功 [{$result->result}] (id=$id) \n"; - if( $is_url ){ - print "种子:".$torrent. "\n"; - } - print "名字:".$name."\n\n"; - return true; - }else{ - $errmsg = isset($result->result) ? $result->result : '未知错误,请稍后重试!'; - print "-----RPC添加种子任务,失败 [{$errmsg}] \n"; - if( $is_url ){ - print "种子:".$torrent. "\n"; - } - } - break; - case 'qBittorrent': - $extra_options['paused'] = 'true'; - $extra_options['autoTMM'] = 'false'; //关闭自动种子管理 - if( $is_url ){ - $result = self::$links[$rpcKey]['rpc']->add( $torrent, $save_path, $extra_options ); // 种子URL添加下载任务 - } else{ - $extra_options['name'] = 'torrents'; - $extra_options['filename'] = rand(1,4294967200).'.torrent'; - $result = self::$links[$rpcKey]['rpc']->add_metainfo( $torrent, $save_path, $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) { - echo '[ERROR] ' . $e->getMessage() . PHP_EOL; - } - return false; - } - - /** - * 正常做种的种子在各下载器的互相转移 - */ - public static function move($torrent=array(), $type = 'qBittorrent'){ - switch($type){ - case 'transmission': - break; - case 'qBittorrent': - foreach ($torrent as $k => $v) { - // 路径转换 - #$v['save_path'] = '/volume3' . $v['save_path']; // docker路径转换 - self::add(self::$move[0], $v['magnet_uri'], $v['save_path'] ); - } - break; - default: - echo '[ERROR] '.$type; - break; - } - } - /** - * @brief 提交种子hash给远端API,用来获取辅种数据 - * @param array $hashArray 种子hash数组 - * @return - */ - public static function call($hashArray = array()) - { - global $configALL; - $resArray = $sites = array(); - $curl = new Curl(); - $curl->setOpt(CURLOPT_SSL_VERIFYPEER, false); - // 签名 - $hashArray['timestamp'] = time(); - // 爱语飞飞token - $hashArray['sign'] = Oauth::getSign(); - $hashArray['version'] = self::VER; - // 写日志 - if (true) { - // 文件句柄 - $resource = fopen(self::$cacheDir.'hashString.txt', "wb"); - // 成功:返回写入字节数,失败返回false - $worldsnum = fwrite($resource, p($hashArray, false)); - fclose($resource); - } - // 发起请求 - echo "正在提交辅种信息…… \n"; - $res = $curl->post(self::$apiUrl . self::$endpoints['reseed'], $hashArray); - $resArray = json_decode($res->response, true); - // 写日志 - if(true){ - // 文件句柄 - $resource = fopen(self::$cacheDir.'reseed.txt', "wb"); - // 成功:返回写入字节数,失败返回false - $worldsnum = fwrite($resource, p($resArray, false)); - fclose($resource); - } - // 判断返回值 - if ( isset($resArray['errmsg']) && ($resArray['errmsg'] == 'ok') ) { - echo "辅种信息提交成功!!! \n\n"; - }else{ - $errmsg = isset($resArray['errmsg']) ? $resArray['errmsg'] : '远端服务器无响应,请稍后重试!'; - echo '-----辅种失败,原因:' .$errmsg. " \n\n"; - exit(1); - } - // 可辅种站点信息列表 - $sites = $resArray['sites']; - self::$wechatMsg['sitesCount'] = count($sites); - #p($sites); - // 按客户端循环辅种 开始 - foreach (self::$links as $k => $v) { - $reseed = $infohash_Dir = array(); - // info_hash 对应的下载目录 - $infohash_Dir = self::$links[$k]['hash']; - if (empty($resArray['clients_'.$k])) { - echo "clients_".$k."没有查询到可辅种数据 \n\n"; - continue; - } - #p($infohash_Dir); - // 当前客户端辅种数据 - $reseed = $resArray['clients_'.$k]; - foreach ($reseed as $info_hash => $vv) { - // 当前种子哈希对应的目录 - $downloadDir = $infohash_Dir[$info_hash]; - foreach ($vv['torrent'] as $id => $value) { - // 匹配的辅种数据累加 - self::$wechatMsg['reseedCount']++; - // 站点id - $sitesID = $value['sid']; - $url = $_url = ''; - $download_page = $details_url = ''; - // 页面规则 - $download_page = str_replace('{}', $value['torrent_id'], $sites[$sitesID]['download_page']); - $_url = 'https://' .$sites[$sitesID]['base_url']. '/' .$download_page; - if ( empty($configALL[$sites[$sitesID]['site']]['passkey']) ) { - echo '-------因当前' .$sites[$sitesID]['site']. '站点未设置passkey,已跳过!!' . "\n\n"; - self::$wechatMsg['reseedSkip']++; - continue; - } - // 种子URL组合方式区分 - switch ($sites[$sitesID]['site']) { - case 'ttg': - $url = $_url."/". $configALL[$sites[$sitesID]['site']]['passkey']; - break; - case 'm-team': - $ip_type = ''; - if (isset($configALL[$sites[$sitesID]['site']]['ip_type'])) { - $ip_type = $configALL[$sites[$sitesID]['site']]['ip_type'] == 'ipv6' ? '&ipv6=1' : ''; - } - $url = $_url."&passkey=". $configALL[$sites[$sitesID]['site']]['passkey'] . $ip_type. "&https=1"; - break; - case 'moecat': - $ip_type = ''; - if (isset($configALL[$sites[$sitesID]['site']]['ip_type'])) { - $ip_type = $configALL[$sites[$sitesID]['site']]['ip_type'] == 'ipv6' ? '&ipv6=1' : ''; - } - $url = $_url."&passkey=". $configALL[$sites[$sitesID]['site']]['passkey'] . $ip_type. "&https=1"; - break; - default: - $url = $_url."&passkey=". $configALL[$sites[$sitesID]['site']]['passkey']; - break; - } - /** - * 检查站点是否可以辅种 - */ - // 判断是否具有VIP或特殊权限? - $is_vip = isset($configALL[$sites[$sitesID]['site']]['is_vip']) && $configALL[$sites[$sitesID]['site']]['is_vip'] ? 1 : 0; - if ( (in_array($sites[$sitesID]['site'], self::$noReseed)==false) || $is_vip ) { - /** - * 可以辅种 - */ - if ( isset($infohash_Dir[$value['info_hash']]) ) { - // 与客户端现有种子重复 - echo '-------与客户端现有种子重复:'.$_url."\n\n"; - self::$wechatMsg['reseedRepeat']++; - continue; - }else{ - // 判断上次是否成功添加? - if ( is_file(self::$cacheHash . $value['info_hash'].'.txt') ) { - echo '-------当前种子上次辅种已成功添加,已跳过!'.$_url."\n\n"; - self::$wechatMsg['reseedPass']++; - continue; - } - // 种子元数据获取 - switch ($sites[$sitesID]['site']) { - case 'hdchina': - if ( empty($configALL[$sites[$sitesID]['site']]['cookie']) ) { - echo '-------因当前' .$sites[$sitesID]['site']. '站点未设置cookie,已跳过!!' . "\n\n"; - self::$wechatMsg['reseedSkip']++; - break; - } - if ( isset($configALL[$sites[$sitesID]['site']]['limit']) ) { - echo "当前站点触发人机验证,已加入排除列表 \n"; - } - $cookie = isset($configALL[$sites[$sitesID]['site']]['cookie']) ? $configALL[$sites[$sitesID]['site']]['cookie'] : ''; - $userAgent = $configALL['default']['userAgent']; - // 拼接URL - $details_page = str_replace('{}', $value['torrent_id'], 'details.php?id={}&hit=1'); - $details_url = 'https://' .$sites[$sitesID]['base_url']. '/' .$details_page; - $details_html = download($details_url, $cookie, $userAgent); - print "种子详情页:".$details_url. "\n"; - // 提取种子下载地址 - $download_page = str_replace('{}', '', $sites[$sitesID]['download_page']); - $offset = strpos($details_html, $download_page); - $urlTemp = substr($details_html, $offset, 50); - // 种子地址 - $_url = substr($urlTemp,0,strpos($urlTemp,'">')); - $_url = 'https://' .$sites[$sitesID]['base_url']. '/' . $_url; - print "种子下载页:".$_url. "\n"; - $url = download($_url, $cookie, $userAgent); - if(strpos($url,'系统检测到过多的种子下载请求') != false){ - echo "触发人机验证 \n"; - ff($sites[$sitesID]['site']. ' 触发人机验证,请重新设置!'); - self::$noReseed[] = 'hdchina'; - $configALL[$sites[$sitesID]['site']]['limit'] = 1; - } - break; - case 'hdcity': - if ( empty($configALL[$sites[$sitesID]['site']]['cookie']) ) { - echo '-------因当前' .$sites[$sitesID]['site']. '站点未设置cookie,已跳过!!' . "\n\n"; - self::$wechatMsg['reseedSkip']++; - break; - } - $cookie = isset($configALL[$sites[$sitesID]['site']]['cookie']) ? $configALL[$sites[$sitesID]['site']]['cookie'] : ''; - $userAgent = $configALL['default']['userAgent']; - print "种子:".$_url. "\n"; - if ( isset($configALL[$sites[$sitesID]['site']]['cuhash']) ) { - // 已获取cuhash - # code... - }else { - // 获取cuhash - $html = download('https://' .$sites[$sitesID]['base_url']. '/pt', $cookie, $userAgent); - // 提取种子下载地址 - $offset = strpos($html,'cuhash='); - $len = strlen('cuhash='); - $cuhashTemp = substr($html,$offset+$len,40); - $configALL[$sites[$sitesID]['site']]['cuhash'] = substr($cuhashTemp,0,strpos($cuhashTemp,'"')); - } - $url = $_url."&cuhash=". $configALL[$sites[$sitesID]['site']]['cuhash']; - // 城市下载种子时会302转向 - $url = download($url, $cookie, $userAgent); - break; - default: - break; - } - // 把拼接的种子URL,推送给下载器 - $ret = false; - // 成功返回:true - $ret = self::add($k, $url, $downloadDir); - // 添加成功的种子,以infohash为文件名,写入缓存 - if ($ret) { - // 成功的种子 - // 文件句柄 - $resource = fopen(self::$cacheHash . $value['info_hash'].'.txt', "wb"); - // 成功:返回写入字节数,失败返回false - $worldsnum = fwrite($resource, $url); - fclose($resource); - self::$wechatMsg['reseedSuccess']++; - continue; - }else{ - // 失败的种子 - // 站点类型判断 - switch ($sites[$sitesID]['site']) { - case 'hdcity': - echo '当前' .$sites[$sitesID]['site']. '站点是配置cuhash(不是passkey),添加成功说明配置正确!如果添加任务失败,请查阅常见问题!!' . "\n"; - break; - default: - break; - } - // 失败累加 - self::$wechatMsg['reseedError']++; - continue; - } - } - }else{ - /** - * 不辅种 - */ - echo '-------已跳过不辅种的站点:'.$_url."\n\n"; - // 写入日志文件,供用户手动辅种 - if ( !isset($infohash_Dir[$value['info_hash']]) ) { - // 站点类型判断 - switch ($sites[$sitesID]['site']) { - case 'hdchina': - $url = $_url; - break; - default: - break; - } - // 文件句柄 - $resource = fopen(self::$cacheDir . $sites[$sitesID]['site'].'.txt', 'a'); - // 成功:返回写入字节数,失败返回false - $worldsnum = fwrite($resource, 'clients_'.$k."\n".$downloadDir."\n".$url."\n".$details_url."\n\n"); - fclose($resource); - } - } - } - } - } - // 按客户端循环辅种 结束 - } - /** - * - */ - public static function wechatMessage(){ - $br = "\r\n"; - $text = 'IYUU自动辅种-统计报表'; - $desp = '总做种:'.self::$wechatMsg['hashCount'] . ' [客户端正在做种的hash总数]' .$br; - $desp .= '返回数据:'.self::$wechatMsg['reseedCount']. ' [服务器返回的可辅种数据]' .$br; - $desp .= '支持站点:'.self::$wechatMsg['sitesCount']. ' [当前支持自动辅种的站点数量]' .$br; - $desp .= '成功:'.self::$wechatMsg['reseedSuccess']. ' [辅种成功,会把hash加入缓存]' .$br; - $desp .= '失败:'.self::$wechatMsg['reseedError']. ' [下载器下载种子失败或网络超时引起,可以重试]' .$br; - $desp .= '重复:'.self::$wechatMsg['reseedRepeat']. ' [客户端已做种]' .$br; - $desp .= '跳过:'.self::$wechatMsg['reseedSkip']. ' [未设置passkey]' .$br; - $desp .= '忽略:'.self::$wechatMsg['reseedPass']. ' [成功添加存在缓存]' .$br; - return ff($text, $desp); - } -} - -/** - * transmission过滤函数,只保留正常做种 - */ -function filterStatus( $v ){ - return isset($v['status']) && $v['status']===6; -} - -/** - * qBittorrent过滤函数,只保留正常做种 - */ -function qbfilterStatus( $v ){ - if( isset($v['state']) && in_array($v['state'], array('uploading','stalledUP','pausedUP','queuedUP','checkingUP','forcedUP')) ){ - - return true; - } - return false; -} -//PHP stdClass Object转array -function object_array($array) { - if(is_object($array)) { - $array = (array)$array; - } - if(is_array($array)) { - foreach($array as $key=>$value) { - $array[$key] = object_array($value); - } - } - return $array; -} -// 对象转数组 -function object2array(&$object) { - return json_decode( json_encode( $object ), true ); -} diff --git a/wiki/数据清理.md b/wiki/数据清理.md deleted file mode 100644 index e72e5ee..0000000 --- a/wiki/数据清理.md +++ /dev/null @@ -1,21 +0,0 @@ -## 404数据最后清理时间 -|标志 | 最后清理时间 | 状态 | -| :-: | :-: | ---- | -| ttg | | | -|城市 | | | -|萌猫 | 2020年1月16日12:07:12 | 已完成 | -|ptmsg | 2020年1月16日12:07:17 | 已完成 | -|瓷器 | | | -|杜比 | 2020年1月16日11:34:19 | 已完成 | -|tccf | | | -|馒头 | | | -|春天 | 2020年1月16日00:23:05 | 已完成 | -|北洋 | 2020年1月16日00:23:05 | 已完成 | -|猫站 | | | -|朋友 | 2020年1月16日00:23:05 | 已完成 | -|铂金家 | 2020年1月16日00:23:05 | 已完成 | -|家园 | 2020年1月16日00:23:05 | 已完成 | -|学校 | 2020年1月16日00:19:24 | 已完成 | -| 我堡 | 2020年1月15日13:56:22 | 已完成 | -| 天空 | 2020年1月15日20:49:33 | 已完成 | -