mirror of
https://github.com/ledccn/IYUUPlus.git
synced 2024-09-20 07:05:28 +00:00
update webman
This commit is contained in:
parent
a0cd0704e6
commit
fb8e6a0234
11
app/Request.php
Normal file
11
app/Request.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace app;
|
||||
|
||||
/**
|
||||
* Class Request
|
||||
* @package support
|
||||
*/
|
||||
class Request extends \support\Request
|
||||
{
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\common;
|
||||
|
||||
/**
|
||||
|
@ -60,6 +61,18 @@ class Config
|
|||
return $writeLen === 0 ? false : $writeLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件路径
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @return string
|
||||
*/
|
||||
public static function createFilePath(string $name = '', string $type = 'array'): string
|
||||
{
|
||||
$ext = self::extMap[$type] ?? self::extMap['object'];
|
||||
return db_path() . DIRECTORY_SEPARATOR . $name . $ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取配置
|
||||
* @param string $filename 文件名
|
||||
|
@ -99,11 +112,11 @@ class Config
|
|||
|
||||
/**
|
||||
* 删除配置
|
||||
* @param string $name
|
||||
* @param string|null $name
|
||||
* @param bool $absolutePath
|
||||
* @return bool
|
||||
*/
|
||||
public static function delete(string $name, bool $absolutePath = false): bool
|
||||
public static function delete(?string $name, bool $absolutePath = false): bool
|
||||
{
|
||||
if ($name === null || $name === '') {
|
||||
return false;
|
||||
|
@ -115,16 +128,4 @@ class Config
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件路径
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @return string
|
||||
*/
|
||||
public static function createFilePath(string $name = '', string $type = 'array'):string
|
||||
{
|
||||
$ext = self::extMap[$type] ?? self::extMap['object'];
|
||||
return db_path() . DIRECTORY_SEPARATOR . $name . $ext;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\common;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\common;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\common\components;
|
||||
|
||||
use app\common\Constant;
|
||||
|
@ -33,6 +34,18 @@ class Curl
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* GET请求
|
||||
* @param string $url
|
||||
* @param array $data 数据
|
||||
* @param bool $reset 是否重置Curl(默认true)
|
||||
* @return ICurl
|
||||
*/
|
||||
public static function get(string $url, array $data = array(), bool $reset = true): ICurl
|
||||
{
|
||||
return static::one($reset)->get($url, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 单例
|
||||
* @param bool $reset
|
||||
|
@ -58,18 +71,6 @@ class Curl
|
|||
return self::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* GET请求
|
||||
* @param string $url
|
||||
* @param array $data 数据
|
||||
* @param bool $reset 是否重置Curl(默认true)
|
||||
* @return ICurl
|
||||
*/
|
||||
public static function get(string $url, array $data = array(), bool $reset = true): ICurl
|
||||
{
|
||||
return static::one($reset)->get($url, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST请求
|
||||
* @param string $url
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\common\event;
|
||||
|
||||
use Throwable;
|
||||
|
@ -8,7 +9,7 @@ use Throwable;
|
|||
* 事件调度器
|
||||
* Class EventDispatcher
|
||||
*/
|
||||
class EventDispatcher implements ListenerProviderInterface, EventDispatcherInterface
|
||||
class EventDispatcher
|
||||
{
|
||||
/**
|
||||
* @var EventListenerInterface
|
||||
|
@ -17,9 +18,9 @@ class EventDispatcher implements ListenerProviderInterface, EventDispatcherInter
|
|||
|
||||
/**
|
||||
* EventDispatcher constructor.
|
||||
* @param EventListenerInterface ...$listeners
|
||||
* @param EventListenerInterface[] $listeners
|
||||
*/
|
||||
public function __construct($listeners)
|
||||
public function __construct(array $listeners)
|
||||
{
|
||||
$eventListeners = [];
|
||||
foreach ($listeners as $listener) {
|
||||
|
@ -30,26 +31,6 @@ class EventDispatcher implements ListenerProviderInterface, EventDispatcherInter
|
|||
$this->eventListeners = $eventListeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检出当前事件的所有监听器
|
||||
*
|
||||
* @param object $event
|
||||
* An event for which to return the relevant listeners.
|
||||
* @return iterable[callable]
|
||||
* An iterable (array, iterator, or generator) of callables. Each
|
||||
* callable MUST be type-compatible with $event.
|
||||
*/
|
||||
public function getListenersForEvent(object $event): iterable
|
||||
{
|
||||
$class = get_class($event);
|
||||
$listeners = $this->eventListeners[$class] ?? [];
|
||||
$iterable = [];
|
||||
foreach ($listeners as $listener) {
|
||||
$iterable[] = [$listener, 'process'];
|
||||
}
|
||||
return $iterable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 派发当前事件到所有监听器的process处理方法
|
||||
*
|
||||
|
@ -71,4 +52,24 @@ class EventDispatcher implements ListenerProviderInterface, EventDispatcherInter
|
|||
}
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检出当前事件的所有监听器
|
||||
*
|
||||
* @param object $event
|
||||
* An event for which to return the relevant listeners.
|
||||
* @return iterable[callable]
|
||||
* An iterable (array, iterator, or generator) of callables. Each
|
||||
* callable MUST be type-compatible with $event.
|
||||
*/
|
||||
public function getListenersForEvent(object $event): iterable
|
||||
{
|
||||
$class = get_class($event);
|
||||
$listeners = $this->eventListeners[$class] ?? [];
|
||||
$iterable = [];
|
||||
foreach ($listeners as $listener) {
|
||||
$iterable[] = [$listener, 'process'];
|
||||
}
|
||||
return $iterable;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\common\event;
|
||||
|
||||
/**
|
||||
* Defines a dispatcher for events.
|
||||
*/
|
||||
interface EventDispatcherInterface
|
||||
{
|
||||
/**
|
||||
* Provide all relevant listeners with an event to process.
|
||||
*
|
||||
* @param object $event
|
||||
* The object to process.
|
||||
*
|
||||
* @return object
|
||||
* The Event that was passed, now modified by listeners.
|
||||
*/
|
||||
public function dispatch(object $event);
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\common\event;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace app\common\event;
|
||||
|
||||
/**
|
||||
* Mapper from an event to the listeners that are applicable to that event.
|
||||
*/
|
||||
interface ListenerProviderInterface
|
||||
{
|
||||
/**
|
||||
* @param object $event
|
||||
* An event for which to return the relevant listeners.
|
||||
* @return iterable[callable]
|
||||
* An iterable (array, iterator, or generator) of callables. Each
|
||||
* callable MUST be type-compatible with $event.
|
||||
*/
|
||||
public function getListenersForEvent(object $event) : iterable;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\common\event;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\common\exception;
|
||||
|
||||
use Exception;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\common\exception;
|
||||
|
||||
use Throwable;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use app\common\exception\BusinessException;
|
||||
use app\common\Constant;
|
||||
use app\domain\Users as domainUsers;
|
||||
use support\Request;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use app\domain\Users as domainUsers;
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use app\common\exception\BusinessException;
|
||||
use app\common\Config as Conf;
|
||||
use app\common\Constant;
|
||||
use app\domain\Config;
|
||||
use IYUU\Reseed\AutoReseed;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain\Command;
|
||||
|
||||
use app\domain\CommandInterface;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain\Command;
|
||||
|
||||
use app\domain\CommandInterface;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain\Command;
|
||||
|
||||
use app\domain\CommandInterface;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain\Command;
|
||||
|
||||
use app\domain\CommandInterface;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain;
|
||||
|
||||
use app\common\Config as Conf;
|
||||
|
@ -127,6 +128,19 @@ class Config
|
|||
return $rs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 排除字段
|
||||
* @param $data
|
||||
*/
|
||||
protected static function createDataExcludeKeys(&$data)
|
||||
{
|
||||
if (is_array($data)) {
|
||||
foreach ([Constant::config_filename, Constant::action] as $key) {
|
||||
unset($data[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 简单操作的增删改查
|
||||
* @param string $config_filename
|
||||
|
@ -141,19 +155,6 @@ class Config
|
|||
return Constant::RS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 排除字段
|
||||
* @param $data
|
||||
*/
|
||||
protected static function createDataExcludeKeys(&$data)
|
||||
{
|
||||
if (is_array($data)) {
|
||||
foreach ([Constant::config_filename, Constant::action] as $key) {
|
||||
unset($data[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IYUU密钥
|
||||
* @return array
|
||||
|
@ -181,15 +182,6 @@ class Config
|
|||
return Conf::get(self::filename['clients'], Constant::config_format, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计划任务
|
||||
* @return array
|
||||
*/
|
||||
public static function getCrontab():array
|
||||
{
|
||||
return Conf::get(self::filename['crontab'], Constant::config_format, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 目录
|
||||
* @return array
|
||||
|
@ -199,15 +191,6 @@ class Config
|
|||
return Conf::get(self::filename['folder'], Constant::config_format, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户拥有的站点
|
||||
* @return array
|
||||
*/
|
||||
public static function getUserSites():array
|
||||
{
|
||||
return Conf::get(self::filename['user_sites'], Constant::config_format, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 所有站点
|
||||
* @return array
|
||||
|
@ -246,6 +229,15 @@ class Config
|
|||
return array_key_exists($uuid, $cron) ? $cron[$uuid] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 计划任务
|
||||
* @return array
|
||||
*/
|
||||
public static function getCrontab(): array
|
||||
{
|
||||
return Conf::get(self::filename['crontab'], Constant::config_format, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用用户已经配置过的站点
|
||||
* @param array $sites
|
||||
|
@ -262,6 +254,15 @@ class Config
|
|||
return $sites;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户拥有的站点
|
||||
* @return array
|
||||
*/
|
||||
public static function getUserSites(): array
|
||||
{
|
||||
return Conf::get(self::filename['user_sites'], Constant::config_format, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用用户未配置的站点
|
||||
* @param array $sites
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain\ConfigParser;
|
||||
|
||||
use app\domain\ConfigParserInterface;
|
||||
|
@ -10,12 +11,13 @@ class Move implements ConfigParserInterface
|
|||
* 路径分隔符
|
||||
*/
|
||||
const Delimiter = '{#**#}';
|
||||
|
||||
/**
|
||||
* 根据参数,解析转移做种的运行时配置
|
||||
* @param string $uuid
|
||||
* @return array
|
||||
*/
|
||||
public static function parser($uuid = ''):array
|
||||
public static function parser(string $uuid = ''): array
|
||||
{
|
||||
$rs = [
|
||||
'clients' => [],
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain\ConfigParser;
|
||||
|
||||
use app\domain\ConfigParserInterface;
|
||||
|
@ -18,7 +19,7 @@ class Reseed implements ConfigParserInterface
|
|||
* @param string $uuid
|
||||
* @return array
|
||||
*/
|
||||
public static function parser($uuid = ''):array
|
||||
public static function parser(string $uuid = ''): array
|
||||
{
|
||||
$rs = [
|
||||
'sites' => [],
|
||||
|
@ -65,6 +66,16 @@ class Reseed implements ConfigParserInterface
|
|||
return $rs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理辅种缓存
|
||||
* @return bool
|
||||
*/
|
||||
public static function clearReseedCache(): bool
|
||||
{
|
||||
$dir = self::getReseedCachePath();
|
||||
return !is_dir($dir) || IFile::rmdir($dir, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取辅种缓存的存放路径
|
||||
* @return string
|
||||
|
@ -74,6 +85,16 @@ class Reseed implements ConfigParserInterface
|
|||
return runtime_path() . DIRECTORY_SEPARATOR . 'torrent' . DIRECTORY_SEPARATOR . 'cachehash';
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理转移缓存
|
||||
* @return bool
|
||||
*/
|
||||
public static function clearMoveCache(): bool
|
||||
{
|
||||
$dir = self::getMoveCachePath();
|
||||
return !is_dir($dir) || IFile::rmdir($dir, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取转移缓存的存放路径
|
||||
* @return string
|
||||
|
@ -82,24 +103,4 @@ class Reseed implements ConfigParserInterface
|
|||
{
|
||||
return runtime_path() . DIRECTORY_SEPARATOR . 'torrent' . DIRECTORY_SEPARATOR . 'cachemove';
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理辅种缓存
|
||||
* @return bool
|
||||
*/
|
||||
public static function clearReseedCache():bool
|
||||
{
|
||||
$dir = self::getReseedCachePath();
|
||||
return is_dir($dir) ? IFile::rmdir($dir, true) : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理转移缓存
|
||||
* @return bool
|
||||
*/
|
||||
public static function clearMoveCache():bool
|
||||
{
|
||||
$dir = self::getMoveCachePath();
|
||||
return is_dir($dir) ? IFile::rmdir($dir, true) : true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain\ConfigParser;
|
||||
|
||||
use app\domain\ConfigParserInterface;
|
||||
|
@ -11,7 +12,7 @@ class Rss implements ConfigParserInterface
|
|||
* @param string $uuid
|
||||
* @return array
|
||||
*/
|
||||
public static function parser($uuid = ''):array
|
||||
public static function parser(string $uuid = ''): array
|
||||
{
|
||||
$rs = [
|
||||
'site' => [],
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain\ConfigParser;
|
||||
|
||||
use app\domain\ConfigParserInterface;
|
||||
|
@ -11,7 +12,7 @@ class Spiders implements ConfigParserInterface
|
|||
* @param string $uuid
|
||||
* @return array
|
||||
*/
|
||||
public static function parser($uuid = ''):array
|
||||
public static function parser(string $uuid = ''): array
|
||||
{
|
||||
return Rss::parser($uuid);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain;
|
||||
|
||||
use app\common\Config as Conf;
|
||||
|
@ -35,24 +36,22 @@ class Crontab
|
|||
const pid_suffix = '.pid';
|
||||
|
||||
// 管理员用户名,用户名密码都为空字符串时说明不用验证
|
||||
public static $adminName = '';
|
||||
|
||||
// 管理员密码,用户名密码都为空字符串时说明不用验证
|
||||
public static $adminPassword = '';
|
||||
|
||||
/**
|
||||
* linux系统的crontab任务永远在第1秒执行,且添加定时任务后的1分钟之内是不会执行该任务(即使语法上完全满足)
|
||||
* @var mixed
|
||||
*/
|
||||
const cron_minute = '%s %s %s %s %s';
|
||||
const cron_second = '%s %s %s %s %s %s';
|
||||
|
||||
// 管理员密码,用户名密码都为空字符串时说明不用验证
|
||||
const cron_second = '%s %s %s %s %s %s';
|
||||
/**
|
||||
* where可能的值
|
||||
*/
|
||||
const WHERE = [
|
||||
'day', 'day_n', 'hour', 'hour_n', 'minute', 'minute_n', 'second', 'second_n', 'week', 'month'
|
||||
];
|
||||
public static $adminName = '';
|
||||
public static $adminPassword = '';
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
|
@ -97,24 +96,6 @@ class Crontab
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除计划任务 钩子
|
||||
* @param string $uuid uuid或文件名
|
||||
* @return bool
|
||||
*/
|
||||
public static function deleteHock(string $uuid):bool
|
||||
{
|
||||
if (empty($uuid)) {
|
||||
return false;
|
||||
}
|
||||
$file_name = self::getFilePath($uuid, self::cron_dir, self::cron_suffix);
|
||||
clearstatcache();
|
||||
if (is_file($file_name)) {
|
||||
return @unlink($file_name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Linux的Crontab语法
|
||||
* @param array $param 数据
|
||||
|
@ -140,12 +121,12 @@ class Crontab
|
|||
public static function parseCron(array $param): string
|
||||
{
|
||||
$cron = '';
|
||||
$where = isset($param['where']) ? $param['where'] : null; //条件
|
||||
$weeks = isset($param['weeks']) ? $param['weeks'] : null; //星期
|
||||
$day = isset($param['day']) ? $param['day'] : null; //天
|
||||
$hour = isset($param['hour']) ? $param['hour'] : null; //时
|
||||
$minute= isset($param['minute']) ? $param['minute'] : null; //分
|
||||
$second= isset($param['second']) ? $param['second'] : '*'; //秒
|
||||
$where = $param['where'] ?? null; //条件
|
||||
$weeks = $param['weeks'] ?? null; //星期
|
||||
$day = $param['day'] ?? null; //天
|
||||
$hour = $param['hour'] ?? null; //时
|
||||
$minute = $param['minute'] ?? null; //分
|
||||
$second = $param['second'] ?? '*'; //秒
|
||||
if ($where === null || !in_array($where, self::WHERE)) {
|
||||
throw new \InvalidArgumentException('Invalid cron param where');
|
||||
}
|
||||
|
@ -198,17 +179,6 @@ class Crontab
|
|||
return Command::parse($param);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建计划任务文件
|
||||
* @param string $filename 文件的完整路径
|
||||
* @param mixed $param 数据
|
||||
* @return bool|int 结果
|
||||
*/
|
||||
public static function writeCronFile($filename, $param)
|
||||
{
|
||||
return Conf::set($filename, $param, 'json', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件路径
|
||||
* @param string $filename 文件名
|
||||
|
@ -216,7 +186,7 @@ class Crontab
|
|||
* @param string $suffix 扩展名
|
||||
* @return string 文件的完整路径
|
||||
*/
|
||||
public static function getFilePath($filename = '', $dir = 'cron_dir', $suffix = '.crontab'):string
|
||||
public static function getFilePath(string $filename = '', string $dir = 'cron_dir', string $suffix = '.crontab'): string
|
||||
{
|
||||
clearstatcache();
|
||||
$_dir = cron_path() . DIRECTORY_SEPARATOR . $dir;
|
||||
|
@ -225,12 +195,41 @@ class Crontab
|
|||
return $_dir . DIRECTORY_SEPARATOR . $filename . $suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建计划任务文件
|
||||
* @param string $filename 文件的完整路径
|
||||
* @param mixed $param 数据
|
||||
* @return bool|int 结果
|
||||
*/
|
||||
public static function writeCronFile(string $filename, $param)
|
||||
{
|
||||
return Conf::set($filename, $param, 'json', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除计划任务 钩子
|
||||
* @param string $uuid uuid或文件名
|
||||
* @return bool
|
||||
*/
|
||||
public static function deleteHock(string $uuid): bool
|
||||
{
|
||||
if (empty($uuid)) {
|
||||
return false;
|
||||
}
|
||||
$file_name = self::getFilePath($uuid, self::cron_dir, self::cron_suffix);
|
||||
clearstatcache();
|
||||
if (is_file($file_name)) {
|
||||
return @unlink($file_name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据任务名字,拼接lock文件路径
|
||||
* @param string $filename
|
||||
* @return string
|
||||
*/
|
||||
public static function getLockFile($filename = ''):string
|
||||
public static function getLockFile(string $filename = ''): string
|
||||
{
|
||||
return self::getFilePath($filename, self::lock_dir, self::lock_suffix);
|
||||
}
|
||||
|
@ -240,21 +239,11 @@ class Crontab
|
|||
* @param string $filename
|
||||
* @return string
|
||||
*/
|
||||
public static function getPidFile($filename = ''):string
|
||||
public static function getPidFile(string $filename = ''): string
|
||||
{
|
||||
return self::getFilePath($filename, self::pid_dir, self::pid_suffix);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接任务log文件的完整路径
|
||||
* @param string $filename
|
||||
* @return string
|
||||
*/
|
||||
public static function getLogFile($filename = ''):string
|
||||
{
|
||||
return self::getFilePath($filename, self::log_dir, '.log');
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据uuid运行任务
|
||||
* @param string $uuid
|
||||
|
@ -273,14 +262,33 @@ class Crontab
|
|||
}
|
||||
|
||||
/**
|
||||
* 读取计划任务的日志
|
||||
* @param string $uuid
|
||||
* @return string
|
||||
* 异步执行命令
|
||||
* @descr 原理为php的程序执行函数后台执行
|
||||
* @param string $cmd 任务执行的命令
|
||||
* @param string $uuid 任务的UUID,通常作为唯一的日志文件名
|
||||
*/
|
||||
public static function readLogs(string $uuid = ''):string
|
||||
public static function execute(string $cmd = '', string $uuid = '')
|
||||
{
|
||||
$logFile = self::getLogFile($uuid);
|
||||
return Conf::get($logFile, 'raw', '', true);
|
||||
// 清理上次的日志
|
||||
self::clearLogs($uuid);
|
||||
// 运行命令
|
||||
if (DIRECTORY_SEPARATOR === '\\') {
|
||||
pclose(popen('start /B ' . $cmd . ' >> ' . $logFile, 'r'));
|
||||
} else {
|
||||
pclose(popen($cmd . ' >> ' . $logFile . ' 2>&1 &', 'r'));
|
||||
//exec($cmd.' >> '.$logFile.' 2>&1 &');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接任务log文件的完整路径
|
||||
* @param string $filename
|
||||
* @return string
|
||||
*/
|
||||
public static function getLogFile(string $filename = ''): string
|
||||
{
|
||||
return self::getFilePath($filename, self::log_dir, '.log');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -295,6 +303,17 @@ class Crontab
|
|||
return is_bool($ret) ? $ret : ($ret >= 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取计划任务的日志
|
||||
* @param string $uuid
|
||||
* @return string
|
||||
*/
|
||||
public static function readLogs(string $uuid = ''): string
|
||||
{
|
||||
$logFile = self::getLogFile($uuid);
|
||||
return Conf::get($logFile, 'raw', '', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理所有计划任务的日志
|
||||
* @return int
|
||||
|
@ -311,24 +330,4 @@ class Crontab
|
|||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步执行命令
|
||||
* @descr 原理为php的程序执行函数后台执行
|
||||
* @param string $cmd 任务执行的命令
|
||||
* @param string $uuid 任务的UUID,通常作为唯一的日志文件名
|
||||
*/
|
||||
public static function execute($cmd = '', $uuid = '')
|
||||
{
|
||||
$logFile = self::getLogFile($uuid);
|
||||
// 清理上次的日志
|
||||
self::clearLogs($uuid);
|
||||
// 运行命令
|
||||
if (DIRECTORY_SEPARATOR === '\\') {
|
||||
pclose(popen('start /B '.$cmd.' >> '.$logFile, 'r'));
|
||||
} else {
|
||||
pclose(popen($cmd.' >> '.$logFile.' 2>&1 &', 'r'));
|
||||
//exec($cmd.' >> '.$logFile.' 2>&1 &');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\domain;
|
||||
|
||||
use support\Request;
|
||||
|
@ -24,6 +25,45 @@ class Users
|
|||
return $session->has(Constant::Session_Token_Key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户绑定
|
||||
* @descr 接口地址 https://api.iyuu.cn/index.php?s=App.User.Login
|
||||
* 接口文档 https://api.iyuu.cn/docs.php?service=App.User.Login&detail=1&type=fold
|
||||
* @param string $token
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public static function bindToken(string $token, Request $request): array
|
||||
{
|
||||
$curl = Curl::one();
|
||||
$url = Constant::API_BASE . Constant::API['login'];
|
||||
$data = [
|
||||
'token' => $token,
|
||||
'id' => $request->post('id') + 0,
|
||||
'passkey' => sha1($request->post('passkey')), // 避免泄露用户密钥passkey
|
||||
'site' => $request->post('site'),
|
||||
];
|
||||
$res = $curl->get($url, $data);
|
||||
$rs = json_decode($res->response, true);
|
||||
if (empty($res->response) || empty($rs) || !is_array($rs)) {
|
||||
$rs = Constant::RS;
|
||||
$rs['ret'] = 500;
|
||||
$rs['msg'] = "用户绑定出错,无法访问{$url}接口,请检查本地网络;或重新创建容器,网络模式改为HOST模式。";
|
||||
return $rs;
|
||||
}
|
||||
if (isset($rs['ret']) && ($rs['ret'] === 200) && isset($rs['data']['success']) && $rs['data']['success']) {
|
||||
//绑定成功
|
||||
return self::checkToken($token, $request);
|
||||
} else {
|
||||
//绑定失败
|
||||
$rs['ret'] = 401;
|
||||
$msg = !empty($rs['msg']) ? $rs['msg'] : '远端服务器无响应,请稍后重试!';
|
||||
$msg = !empty($rs['data']['errmsg']) ? $rs['data']['errmsg'] : $msg;
|
||||
$rs['msg'] = $msg;
|
||||
return $rs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查token及绑定状态
|
||||
* - 接口api.iyuu.cn返回的信息,原样返回给前端
|
||||
|
@ -69,45 +109,6 @@ class Users
|
|||
return $rs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户绑定
|
||||
* @descr 接口地址 https://api.iyuu.cn/index.php?s=App.User.Login
|
||||
* 接口文档 https://api.iyuu.cn/docs.php?service=App.User.Login&detail=1&type=fold
|
||||
* @param string $token
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public static function bindToken(string $token, Request $request):array
|
||||
{
|
||||
$curl = Curl::one();
|
||||
$url = Constant::API_BASE . Constant::API['login'];
|
||||
$data = [
|
||||
'token' => $token,
|
||||
'id' => $request->post('id') + 0,
|
||||
'passkey'=> sha1($request->post('passkey')), // 避免泄露用户密钥passkey
|
||||
'site' => $request->post('site'),
|
||||
];
|
||||
$res = $curl->get($url, $data);
|
||||
$rs = json_decode($res->response, true);
|
||||
if (empty($res->response) || empty($rs) || !is_array($rs)) {
|
||||
$rs = Constant::RS;
|
||||
$rs['ret'] = 500;
|
||||
$rs['msg'] = "用户绑定出错,无法访问{$url}接口,请检查本地网络;或重新创建容器,网络模式改为HOST模式。";
|
||||
return $rs;
|
||||
}
|
||||
if (isset($rs['ret']) && ($rs['ret'] === 200) && isset($rs['data']['success']) && $rs['data']['success']) {
|
||||
//绑定成功
|
||||
return self::checkToken($token, $request);
|
||||
} else {
|
||||
//绑定失败
|
||||
$rs['ret'] = 401;
|
||||
$msg = !empty($rs['msg']) ? $rs['msg'] : '远端服务器无响应,请稍后重试!';
|
||||
$msg = !empty($rs['data']['errmsg']) ? $rs['data']['errmsg'] : $msg;
|
||||
$rs['msg'] = $msg;
|
||||
return $rs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户输入的密码
|
||||
* @param Request $request
|
||||
|
@ -134,6 +135,15 @@ class Users
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户特征文件名
|
||||
* @return string
|
||||
*/
|
||||
public static function getUserProfileName(): string
|
||||
{
|
||||
return 'userProfile';
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户密码
|
||||
* @param string $password
|
||||
|
@ -170,13 +180,4 @@ class Users
|
|||
{
|
||||
return md5($salt . $password . $salt);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户特征文件名
|
||||
* @return string
|
||||
*/
|
||||
public static function getUserProfileName():string
|
||||
{
|
||||
return 'userProfile';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
<?php
|
||||
/**
|
||||
* 自定义函数
|
||||
* 【载入时机】worker子进程
|
||||
*/
|
||||
|
||||
use app\common\components\Curl as ICurl;
|
||||
use app\domain\Config as domainConfig;
|
||||
|
||||
|
|
114
app/helpers.php
Normal file
114
app/helpers.php
Normal file
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
/**
|
||||
* 自定义函数
|
||||
* 【载入时机】composer.json
|
||||
*/
|
||||
/**
|
||||
* 数据目录
|
||||
* @return string
|
||||
*/
|
||||
function db_path(): string
|
||||
{
|
||||
return base_path() . DIRECTORY_SEPARATOR . 'db';
|
||||
}
|
||||
|
||||
/**
|
||||
* 计划任务目录
|
||||
*/
|
||||
function cron_path(): string
|
||||
{
|
||||
return runtime_path() . DIRECTORY_SEPARATOR . 'crontab';
|
||||
}
|
||||
|
||||
if (!function_exists('env')) {
|
||||
/**
|
||||
* @param $key
|
||||
* @param null $default
|
||||
* @return array|bool|string|null
|
||||
*/
|
||||
function env($key, $default = null)
|
||||
{
|
||||
$value = getenv($key);
|
||||
|
||||
if ($value === false) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
switch (strtolower($value)) {
|
||||
case 'true':
|
||||
case '(true)':
|
||||
return true;
|
||||
case 'false':
|
||||
case '(false)':
|
||||
return false;
|
||||
case 'empty':
|
||||
case '(empty)':
|
||||
return '';
|
||||
case 'null':
|
||||
case '(null)':
|
||||
return null;
|
||||
}
|
||||
|
||||
if (($valueLength = strlen($value)) > 1 && $value[0] === '"' && $value[$valueLength - 1] === '"') {
|
||||
return substr($value, 1, -1);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CLI打印调试
|
||||
* @param $data
|
||||
* @param bool $echo
|
||||
* @return string
|
||||
*/
|
||||
function cli($data, bool $echo = true): string
|
||||
{
|
||||
$str = '----------------------------------------date:' . date("Y-m-d H:i:s") . PHP_EOL;
|
||||
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 .= PHP_EOL . '----------------------------------------memory_get_usage:' . memory_get_usage(true) . PHP_EOL . PHP_EOL;
|
||||
if ($echo) {
|
||||
echo $str;
|
||||
return '';
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否win平台
|
||||
* @return bool
|
||||
*/
|
||||
function isWin(): bool
|
||||
{
|
||||
return DIRECTORY_SEPARATOR === '\\';
|
||||
}
|
||||
|
||||
/**
|
||||
* 对布尔型进行格式化
|
||||
* @param mixed $value 变量值
|
||||
* @return boolean string 格式化后的变量
|
||||
*/
|
||||
function booleanParse($value): bool
|
||||
{
|
||||
$rs = $value;
|
||||
|
||||
if (!is_bool($value)) {
|
||||
if (is_numeric($value)) {
|
||||
$rs = ($value + 0) > 0;
|
||||
} elseif (is_string($value)) {
|
||||
$rs = in_array(strtolower($value), ['ok', 'true', 'success', 'on', 'yes', '(ok)', '(true)', '(success)', '(on)', '(yes)']);
|
||||
} else {
|
||||
$rs = (bool)$value;
|
||||
}
|
||||
}
|
||||
|
||||
return $rs;
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace support\middleware;
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
|
@ -1,44 +0,0 @@
|
|||
<?php
|
||||
namespace app\middleware;
|
||||
|
||||
use support\bootstrap\Container;
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
||||
use Webman\Http\Request;
|
||||
|
||||
/**
|
||||
* [中间件] 控制器钩子
|
||||
* @descr 每个控制器执行前调用beforeAction(),执行后调用afterAction()
|
||||
* Class ActionHook
|
||||
* @package app\middleware
|
||||
*/
|
||||
class ActionHook implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $next) : Response
|
||||
{
|
||||
if ($request->controller) {
|
||||
// 禁止直接访问beforeAction afterAction
|
||||
if ($request->action === 'beforeAction' || $request->action === 'afterAction') {
|
||||
return response('<h1>404 Not Found</h1>', 404);
|
||||
}
|
||||
$controller = Container::get($request->controller);
|
||||
//请求前的流程
|
||||
if (method_exists($controller, 'beforeAction')) {
|
||||
$before_response = call_user_func([$controller, 'beforeAction'], $request);
|
||||
if ($before_response instanceof Response) {
|
||||
return $before_response;
|
||||
}
|
||||
}
|
||||
$response = $next($request);
|
||||
//请求后的流程
|
||||
if (method_exists($controller, 'afterAction')) {
|
||||
$after_response = call_user_func([$controller, 'afterAction'], $request, $response);
|
||||
if ($after_response instanceof Response) {
|
||||
return $after_response;
|
||||
}
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace support\middleware;
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
|
@ -1,28 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
class Test extends Model
|
||||
{
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'test';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||
<link href="/favicon.ico" rel="shortcut icon"/>
|
||||
<title>webman</title>
|
||||
|
||||
</head>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<?php
|
||||
require_once dirname(__DIR__) . '/init.php';
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||
require_once ROOT_PATH . '/app/functions.php';
|
||||
require_once ROOT_PATH . '/src/helper.php';
|
||||
echo microtime(true) . ' 当前脚本路径:' . __FILE__ . PHP_EOL;
|
||||
|
||||
use IYUU\Reseed\AutoReseed;
|
||||
use Workerman\Autoloader;
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<?php
|
||||
require_once dirname(__DIR__) . '/init.php';
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||
require_once ROOT_PATH . '/app/functions.php';
|
||||
require_once ROOT_PATH . '/src/helper.php';
|
||||
echo microtime(true) . ' 当前脚本路径:' . __FILE__ . PHP_EOL;
|
||||
|
||||
use IYUU\Reseed\MoveTorrent;
|
||||
use Workerman\Autoloader;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
require_once dirname(__DIR__) . '/init.php';
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||
require_once ROOT_PATH . '/app/functions.php';
|
||||
require_once ROOT_PATH . '/src/helper.php';
|
||||
echo microtime(true) . ' 当前脚本路径:' . __FILE__ . PHP_EOL;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
require_once dirname(__DIR__) . '/init.php';
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||
require_once ROOT_PATH . '/app/functions.php';
|
||||
require_once ROOT_PATH . '/src/helper.php';
|
||||
echo microtime(true) . ' 当前脚本路径:' . __FILE__ . PHP_EOL;
|
||||
|
|
|
@ -25,8 +25,9 @@
|
|||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"workerman/webman-framework": "^1.0",
|
||||
"workerman/webman-framework": "^1.4.7",
|
||||
"monolog/monolog": "^2.0",
|
||||
"webman/console": "^1.2.12",
|
||||
"vlucas/phpdotenv": "5.1.0",
|
||||
"rhilip/bencode": "^2.1",
|
||||
"workerman/crontab": "^1.0",
|
||||
|
@ -37,22 +38,36 @@
|
|||
"ext-mbstring": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-dom": "*",
|
||||
"ledccn/bittorrentclient": "dev-master"
|
||||
"ledccn/bittorrentclient": "dev-master",
|
||||
"webman/event": "^1.0",
|
||||
"ext-simplexml": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-event": "For better performance. "
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"": "./",
|
||||
"IYUU\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"./support/helpers.php"
|
||||
"./init.php",
|
||||
"./support/helpers.php",
|
||||
"./app/helpers.php"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"post-autoload-dump": [
|
||||
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||
],
|
||||
"post-package-install": [
|
||||
"support\\Plugin::install"
|
||||
],
|
||||
"post-package-update": [
|
||||
"support\\Plugin::install"
|
||||
],
|
||||
"pre-package-uninstall": [
|
||||
"support\\Plugin::uninstall"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use app\Request;
|
||||
|
||||
return [
|
||||
'debug' => env('APP_DEBUG', false),
|
||||
'default_timezone' => 'Asia/Shanghai',
|
||||
'error_reporting' => E_ALL,
|
||||
'request_class' => Request::class,
|
||||
'public_path' => base_path() . DIRECTORY_SEPARATOR . 'public',
|
||||
'runtime_path' => base_path(false) . DIRECTORY_SEPARATOR . 'runtime',
|
||||
'controller_suffix' => '',
|
||||
//关闭控制器复用,每个请求都会触发对应控制器的__construct()构造函数
|
||||
'controller_reuse' => false,
|
||||
];
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
return [
|
||||
'files' => [
|
||||
base_path() . '/app/functions.php'
|
||||
base_path() . '/app/functions.php',
|
||||
base_path() . '/app/Request.php',
|
||||
base_path() . '/support/Response.php',
|
||||
]
|
||||
];
|
||||
|
|
|
@ -13,10 +13,5 @@
|
|||
*/
|
||||
|
||||
return [
|
||||
support\bootstrap\Container::class,
|
||||
support\bootstrap\Session::class,
|
||||
//support\bootstrap\db\Laravel::class,
|
||||
//support\bootstrap\Redis::class,
|
||||
support\bootstrap\Log::class,
|
||||
support\bootstrap\Translation::class,
|
||||
];
|
||||
|
|
|
@ -1,6 +1,2 @@
|
|||
<?php
|
||||
return [
|
||||
'EventListener' => [
|
||||
IYUU\Library\EventListen\send::class,
|
||||
],
|
||||
];
|
||||
return [];
|
||||
|
|
|
@ -19,6 +19,7 @@ return [
|
|||
'class' => Monolog\Handler\RotatingFileHandler::class,
|
||||
'constructor' => [
|
||||
runtime_path() . '/logs/webman.log',
|
||||
7, //$maxFiles
|
||||
Monolog\Logger::DEBUG,
|
||||
],
|
||||
'formatter' => [
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
return [
|
||||
'' => [
|
||||
app\middleware\AuthCheck::class,
|
||||
app\middleware\ActionHook::class,
|
||||
//support\middleware\AuthCheckTest::class,
|
||||
//support\middleware\AccessControlTest::class,
|
||||
]
|
||||
];
|
||||
|
|
|
@ -19,8 +19,8 @@ use support\view\ThinkPHP;
|
|||
|
||||
return [
|
||||
// 文件更新检测
|
||||
'IYUUFileMonitor' => [
|
||||
'handler' => process\FileMonitor::class,
|
||||
'monitor' => [
|
||||
'handler' => process\Monitor::class,
|
||||
'reloadable' => false,
|
||||
'constructor' => [
|
||||
// 监控这些目录
|
||||
|
@ -30,12 +30,13 @@ return [
|
|||
base_path() . '/process',
|
||||
base_path() . '/src',
|
||||
base_path() . '/support',
|
||||
base_path() . '/resource'
|
||||
base_path() . '/resource',
|
||||
base_path() . '/.env',
|
||||
],
|
||||
// Files with these suffixes will be monitored
|
||||
'monitor_extensions' => [
|
||||
'php', 'html', 'htm', 'env'
|
||||
],
|
||||
// 监控这些后缀的文件
|
||||
'monitor_extenstions' => [
|
||||
'php', 'html', 'htm'
|
||||
]
|
||||
]
|
||||
],
|
||||
// 其它进程
|
||||
|
|
|
@ -3,13 +3,16 @@ return [
|
|||
'listen' => 'http://0.0.0.0:8787',
|
||||
'transport' => 'tcp',
|
||||
'context' => [],
|
||||
'name' => 'IYUUAutoReseed',
|
||||
'name' => 'IYUUPlus',
|
||||
'count' => env('SERVER_PROCESS_COUNT', 2),
|
||||
'user' => env('SERVER_PROCESS_USER', ''),
|
||||
'group' => env('SERVER_PROCESS_GROUP', ''),
|
||||
'event_loop' => '',
|
||||
'stop_timeout' => 2,
|
||||
'pid_file' => runtime_path() . '/webman.pid',
|
||||
'log_file' => runtime_path() . '/workerman.log',
|
||||
'max_request' => 1000,
|
||||
'status_file' => runtime_path() . '/webman.status',
|
||||
'stdout_file' => runtime_path() . '/logs/stdout.log',
|
||||
'max_request' => 1000,
|
||||
'max_package_size' => 10 * 1024 * 1024
|
||||
];
|
||||
|
|
|
@ -16,7 +16,7 @@ return [
|
|||
|
||||
'type' => 'file', // or redis or redis_cluster
|
||||
|
||||
'handler' => Webman\FileSessionHandler::class,
|
||||
'handler' => Webman\Session\FileSessionHandler::class,
|
||||
|
||||
'config' => [
|
||||
'file' => [
|
||||
|
|
|
@ -18,6 +18,6 @@
|
|||
return [
|
||||
'enable' => true, // 是否支持静态文件
|
||||
'middleware' => [ // 静态文件中间件
|
||||
support\middleware\StaticFile::class,
|
||||
app\middleware\StaticFile::class,
|
||||
],
|
||||
];
|
||||
|
|
3
init.php
3
init.php
|
@ -24,9 +24,6 @@ echo microtime(true).' 当前运行环境:'.PHP_OS_FAMILY.PHP_EOL;
|
|||
echo microtime(true) . ' 当前接口类型:' . PHP_SAPI . PHP_EOL;
|
||||
echo microtime(true) . ' PHP二进制文件:' . PHP_BINARY . PHP_EOL;
|
||||
echo microtime(true) . ' PHP版本号:' . PHP_VERSION . PHP_EOL;
|
||||
echo microtime(true).' 正在加载composer包管理器...'.PHP_EOL;
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
echo microtime(true).' composer依赖载入完成!'.PHP_EOL;
|
||||
|
||||
// 定义目录
|
||||
defined('ROOT_PATH') or define('ROOT_PATH', __DIR__);
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace process;
|
||||
|
||||
use Workerman\Timer;
|
||||
use Workerman\Worker;
|
||||
|
||||
class FileMonitor
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $_paths = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $_extensions = [];
|
||||
|
||||
/**
|
||||
* pidFile
|
||||
*/
|
||||
const pidFile = 'IYUUFileMonitor.pid';
|
||||
|
||||
/**
|
||||
* FileMonitor constructor.
|
||||
* @param $monitor_dir
|
||||
* @param $monitor_extenstions
|
||||
*/
|
||||
public function __construct($monitor_dir, $monitor_extenstions)
|
||||
{
|
||||
if (function_exists('posix_getpid')) {
|
||||
\file_put_contents(runtime_path() . \DIRECTORY_SEPARATOR . self::pidFile, \posix_getpid());
|
||||
}
|
||||
if (Worker::$daemonize) {
|
||||
#return;
|
||||
}
|
||||
$this->_paths = (array)$monitor_dir;
|
||||
$this->_extensions = $monitor_extenstions;
|
||||
Timer::add(1, function () {
|
||||
foreach ($this->_paths as $path) {
|
||||
$this->check_files_change($path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 析构方法
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
is_file(runtime_path() . \DIRECTORY_SEPARATOR . self::pidFile) and @\unlink(runtime_path() . \DIRECTORY_SEPARATOR . self::pidFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $monitor_dir
|
||||
*/
|
||||
public function check_files_change($monitor_dir)
|
||||
{
|
||||
static $last_mtime;
|
||||
if (!$last_mtime) {
|
||||
$last_mtime = time();
|
||||
}
|
||||
|
||||
clearstatcache();
|
||||
|
||||
if (!is_dir($monitor_dir)) {
|
||||
return;
|
||||
}
|
||||
// recursive traversal directory
|
||||
$dir_iterator = new \RecursiveDirectoryIterator($monitor_dir);
|
||||
$iterator = new \RecursiveIteratorIterator($dir_iterator);
|
||||
foreach ($iterator as $file) {
|
||||
/** var SplFileInfo $file */
|
||||
if (is_dir($file)) {
|
||||
continue;
|
||||
}
|
||||
// check mtime
|
||||
if ($last_mtime < $file->getMTime() && in_array($file->getExtension(), $this->_extensions)) {
|
||||
$var = 0;
|
||||
exec("php -l " . $file, $out, $var);
|
||||
if ($var) {
|
||||
$last_mtime = $file->getMTime();
|
||||
continue;
|
||||
}
|
||||
echo $file . " update and reload\n";
|
||||
// send SIGUSR1 signal to master process for reload
|
||||
posix_kill(posix_getppid(), SIGUSR1);
|
||||
$last_mtime = $file->getMTime();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
195
process/Monitor.php
Normal file
195
process/Monitor.php
Normal file
|
@ -0,0 +1,195 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace process;
|
||||
|
||||
use Workerman\Timer;
|
||||
use Workerman\Worker;
|
||||
|
||||
/**
|
||||
* Class FileMonitor
|
||||
* @package process
|
||||
*/
|
||||
class Monitor
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $_paths = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $_extensions = [];
|
||||
|
||||
/**
|
||||
* FileMonitor constructor.
|
||||
* @param $monitor_dir
|
||||
* @param $monitor_extensions
|
||||
* @param $memory_limit
|
||||
*/
|
||||
public function __construct($monitor_dir, $monitor_extensions, $memory_limit = null)
|
||||
{
|
||||
$this->_paths = (array)$monitor_dir;
|
||||
$this->_extensions = $monitor_extensions;
|
||||
if (!Worker::getAllWorkers()) {
|
||||
return;
|
||||
}
|
||||
$disable_functions = explode(',', ini_get('disable_functions'));
|
||||
if (in_array('exec', $disable_functions, true)) {
|
||||
echo "\nMonitor file change turned off because exec() has been disabled by disable_functions setting in " . PHP_CONFIG_FILE_PATH . "/php.ini\n";
|
||||
} else {
|
||||
if (!Worker::$daemonize) {
|
||||
Timer::add(1, function () {
|
||||
$this->checkAllFilesChange();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$memory_limit = $this->getMemoryLimit($memory_limit);
|
||||
if ($memory_limit && DIRECTORY_SEPARATOR === '/') {
|
||||
Timer::add(60, [$this, 'checkMemory'], [$memory_limit]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $monitor_dir
|
||||
*/
|
||||
public function checkFilesChange($monitor_dir)
|
||||
{
|
||||
static $last_mtime, $too_many_files_check;
|
||||
if (!$last_mtime) {
|
||||
$last_mtime = time();
|
||||
}
|
||||
clearstatcache();
|
||||
if (!is_dir($monitor_dir)) {
|
||||
if (!is_file($monitor_dir)) {
|
||||
return;
|
||||
}
|
||||
$iterator = [new \SplFileInfo($monitor_dir)];
|
||||
} else {
|
||||
// recursive traversal directory
|
||||
$dir_iterator = new \RecursiveDirectoryIterator($monitor_dir, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS);
|
||||
$iterator = new \RecursiveIteratorIterator($dir_iterator);
|
||||
}
|
||||
$count = 0;
|
||||
foreach ($iterator as $file) {
|
||||
$count ++;
|
||||
/** var SplFileInfo $file */
|
||||
if (is_dir($file)) {
|
||||
continue;
|
||||
}
|
||||
// check mtime
|
||||
if ($last_mtime < $file->getMTime() && in_array($file->getExtension(), $this->_extensions, true)) {
|
||||
$var = 0;
|
||||
exec('"'.PHP_BINARY . '" -l ' . $file, $out, $var);
|
||||
if ($var) {
|
||||
$last_mtime = $file->getMTime();
|
||||
continue;
|
||||
}
|
||||
$last_mtime = $file->getMTime();
|
||||
echo $file . " update and reload\n";
|
||||
// send SIGUSR1 signal to master process for reload
|
||||
if (DIRECTORY_SEPARATOR === '/') {
|
||||
posix_kill(posix_getppid(), SIGUSR1);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$too_many_files_check && $count > 1000) {
|
||||
echo "Monitor: There are too many files ($count files) in $monitor_dir which makes file monitoring very slow\n";
|
||||
$too_many_files_check = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function checkAllFilesChange()
|
||||
{
|
||||
foreach ($this->_paths as $path) {
|
||||
if ($this->checkFilesChange($path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $memory_limit
|
||||
* @return void
|
||||
*/
|
||||
public function checkMemory($memory_limit)
|
||||
{
|
||||
$ppid = posix_getppid();
|
||||
$children_file = "/proc/$ppid/task/$ppid/children";
|
||||
if (!is_file($children_file) || !($children = file_get_contents($children_file))) {
|
||||
return;
|
||||
}
|
||||
foreach (explode(' ', $children) as $pid) {
|
||||
$pid = (int)$pid;
|
||||
$status_file = "/proc/$pid/status";
|
||||
if (!is_file($status_file) || !($status = file_get_contents($status_file))) {
|
||||
continue;
|
||||
}
|
||||
$mem = 0;
|
||||
if (preg_match('/VmRSS\s*?:\s*?(\d+?)\s*?kB/', $status, $match)) {
|
||||
$mem = $match[1];
|
||||
}
|
||||
$mem = (int)($mem / 1024);
|
||||
if ($mem >= $memory_limit) {
|
||||
posix_kill($pid, SIGINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory limit
|
||||
* @return float
|
||||
*/
|
||||
protected function getMemoryLimit($memory_limit)
|
||||
{
|
||||
if ($memory_limit === 0) {
|
||||
return 0;
|
||||
}
|
||||
$use_php_ini = false;
|
||||
if (!$memory_limit) {
|
||||
$memory_limit = ini_get('memory_limit');
|
||||
$use_php_ini = true;
|
||||
}
|
||||
|
||||
if ($memory_limit == -1) {
|
||||
return 0;
|
||||
}
|
||||
$unit = $memory_limit[strlen($memory_limit) - 1];
|
||||
if ($unit == 'G') {
|
||||
$memory_limit = 1024 * (int)$memory_limit;
|
||||
} else if ($unit == 'M') {
|
||||
$memory_limit = (int)$memory_limit;
|
||||
} else if ($unit == 'K') {
|
||||
$memory_limit = (int)($memory_limit / 1024);
|
||||
} else {
|
||||
$memory_limit = (int)($memory_limit / (1024 * 1024));
|
||||
}
|
||||
if ($memory_limit < 30) {
|
||||
$memory_limit = 30;
|
||||
}
|
||||
if ($use_php_ini) {
|
||||
$memory_limit = (int)(0.8 * $memory_limit);
|
||||
}
|
||||
return $memory_limit;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace IYUU\Library;
|
||||
|
||||
/**
|
||||
|
@ -71,6 +72,39 @@ class Context
|
|||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除指定Session
|
||||
* @param string $key
|
||||
* @return Context
|
||||
*/
|
||||
public function unsetSession(string $key): Context
|
||||
{
|
||||
unset($this->session[$key]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取不可访问属性的值时,__get() 会被调用
|
||||
*
|
||||
* @param string $name 参数名字
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get(string $name)
|
||||
{
|
||||
return $this->getSession($name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在给不可访问属性赋值时,__set() 会被调用
|
||||
*
|
||||
* @param string $name 参数名字
|
||||
* @param mixed $value 参数解析后的值
|
||||
*/
|
||||
public function __set(string $name, $value)
|
||||
{
|
||||
$this->setSession($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Session
|
||||
* @param string|null $key
|
||||
|
@ -105,39 +139,6 @@ class Context
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除指定Session
|
||||
* @param string $key
|
||||
* @return Context
|
||||
*/
|
||||
public function unsetSession(string $key): Context
|
||||
{
|
||||
unset($this->session[$key]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取不可访问属性的值时,__get() 会被调用
|
||||
*
|
||||
* @param string $name 参数名字
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get(string $name)
|
||||
{
|
||||
return $this->getSession($name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在给不可访问属性赋值时,__set() 会被调用
|
||||
*
|
||||
* @param string $name 参数名字
|
||||
* @param mixed $value 参数解析后的值
|
||||
*/
|
||||
public function __set(string $name, $value)
|
||||
{
|
||||
$this->setSession($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用
|
||||
*
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
namespace IYUU\Library\EventListen;
|
||||
|
||||
use app\common\event\EventListenerInterface;
|
||||
|
||||
class send implements EventListenerInterface
|
||||
{
|
||||
/**
|
||||
* 需要订阅的事件
|
||||
* - 返回要监听的事件数组,可监听多个事件
|
||||
* @return array
|
||||
*/
|
||||
public function events():array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅器的处理方法(事件触发后,会执行该方法)
|
||||
*
|
||||
* @param object $event
|
||||
*/
|
||||
public function process(object $event):void
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace IYUU\Library;
|
||||
|
||||
/**
|
||||
|
@ -8,6 +9,7 @@ namespace IYUU\Library;
|
|||
class IFile
|
||||
{
|
||||
private $resource = null; //文件资源句柄
|
||||
|
||||
/**
|
||||
* @brief 构造函数,打开资源流,并独占锁定
|
||||
* @param String $fileName 文件路径名
|
||||
|
@ -34,55 +36,15 @@ class IFile
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief 获取文件内容
|
||||
* @return String 文件内容
|
||||
* @brief 创建文件夹
|
||||
* @param String $path 路径
|
||||
* @param int $chmod 文件夹权限
|
||||
* @note $chmod 参数不能是字符串(加引号),否则linux会出现权限问题
|
||||
* @return bool
|
||||
*/
|
||||
public function read()
|
||||
public static function mkdir($path, $chmod = 0777)
|
||||
{
|
||||
$content = null;
|
||||
while (!feof($this->resource)) {
|
||||
$content.= fread($this->resource, 1024);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 $dir
|
||||
* @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;
|
||||
}
|
||||
return is_dir($path) or (self::mkdir(dirname($path), $chmod) and mkdir($path, $chmod));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,18 +61,6 @@ class IFile
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 创建文件夹
|
||||
* @param String $path 路径
|
||||
* @param int $chmod 文件夹权限
|
||||
* @note $chmod 参数不能是字符串(加引号),否则linux会出现权限问题
|
||||
* @return bool
|
||||
*/
|
||||
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 源文件路径
|
||||
|
@ -164,9 +114,7 @@ class IFile
|
|||
if ($recursive == true) {
|
||||
self::clearDir($dir);
|
||||
return self::rmdir($dir, false);
|
||||
}
|
||||
|
||||
//非强制删除
|
||||
} //非强制删除
|
||||
else {
|
||||
if (rmdir($dir)) {
|
||||
return true;
|
||||
|
@ -178,6 +126,33 @@ class IFile
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 清空目录下的所有文件
|
||||
* @param string $dir
|
||||
* @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 $fileName 文件名
|
||||
|
@ -268,14 +243,6 @@ class IFile
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 释放文件锁定
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
flock($this->resource, LOCK_UN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取文件扩展名
|
||||
* @param String $fileName 文件名
|
||||
|
@ -287,6 +254,39 @@ class IFile
|
|||
return $fileInfoArray['extension'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取文件内容
|
||||
* @return String 文件内容
|
||||
*/
|
||||
public function read()
|
||||
{
|
||||
$content = null;
|
||||
while (!feof($this->resource)) {
|
||||
$content .= fread($this->resource, 1024);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 释放文件锁定
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
flock($this->resource, LOCK_UN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 析构函数,释放文件连接句柄
|
||||
*/
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* Rpc操作类
|
||||
* 把RSS解码与添加下载任务解耦
|
||||
*/
|
||||
|
||||
namespace IYUU\Library;
|
||||
|
||||
use IYUU\Client\AbstractClient;
|
||||
|
@ -10,8 +11,12 @@ use IYUU\Client\AbstractClient;
|
|||
class Rpc
|
||||
{
|
||||
// 站点标识
|
||||
protected static $site = '';
|
||||
/**
|
||||
* 退出状态码
|
||||
*/
|
||||
public static $ExitCode = 0;
|
||||
// 下载种子的请求类型 GET POST
|
||||
protected static $site = '';
|
||||
protected static $method = 'GET';
|
||||
/**
|
||||
* 运行时解析的配置
|
||||
|
@ -50,10 +55,6 @@ class Rpc
|
|||
* RPC连接
|
||||
*/
|
||||
protected static $links = array();
|
||||
/**
|
||||
* 退出状态码
|
||||
*/
|
||||
public static $ExitCode = 0;
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace IYUU\Library;
|
||||
|
||||
use DOMDocument;
|
||||
|
@ -6,10 +7,10 @@ use DOMXpath;
|
|||
|
||||
class Selector
|
||||
{
|
||||
public static $error = null;
|
||||
private static $dom = null;
|
||||
private static $dom_auth = '';
|
||||
private static $xpath = null;
|
||||
public static $error = null;
|
||||
|
||||
/**
|
||||
* @param $html
|
||||
|
@ -36,36 +37,6 @@ class Selector
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $html
|
||||
* @param string $selector
|
||||
* @param string $selector_type
|
||||
* @return mixed|null
|
||||
*/
|
||||
public static function remove($html, $selector, $selector_type = 'xpath')
|
||||
{
|
||||
if (empty($html) || empty($selector)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$selector_type = strtolower($selector_type);
|
||||
switch ($selector_type) {
|
||||
case 'xpath':
|
||||
$remove_html = self::_xpath_select($html, $selector, true);
|
||||
break;
|
||||
case 'regex':
|
||||
$remove_html = self::_regex_select($html, $selector, true);
|
||||
break;
|
||||
case 'css':
|
||||
$remove_html = self::_css_select($html, $selector, true);
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
return str_replace($remove_html, '', $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* xpath选择器
|
||||
*
|
||||
|
@ -111,8 +82,7 @@ class Selector
|
|||
// 如果是img标签,直接取src值
|
||||
if ($nodeType == 1 && in_array($nodeName, array('img'))) {
|
||||
$content = $element->getAttribute('src');
|
||||
}
|
||||
// 如果是标签属性,直接取节点值
|
||||
} // 如果是标签属性,直接取节点值
|
||||
elseif ($nodeType == 2 || $nodeType == 3 || $nodeType == 4) {
|
||||
$content = $element->nodeValue;
|
||||
} else {
|
||||
|
@ -132,20 +102,6 @@ class Selector
|
|||
return count($result) > 1 ? $result : $result[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* css选择器
|
||||
*
|
||||
* @param $html
|
||||
* @param string $selector
|
||||
* @param bool $remove
|
||||
* @return array|string|null
|
||||
*/
|
||||
private static function _css_select($html, $selector, $remove = false)
|
||||
{
|
||||
$selector = self::css_to_xpath($selector);
|
||||
return self::_xpath_select($html, $selector, $remove);
|
||||
}
|
||||
|
||||
/**
|
||||
* 正则选择器
|
||||
*
|
||||
|
@ -165,8 +121,7 @@ class Selector
|
|||
// 一个都没有匹配到
|
||||
if ($count === 0) {
|
||||
return null;
|
||||
}
|
||||
// 只匹配一个,就是只有一个 ()
|
||||
} // 只匹配一个,就是只有一个 ()
|
||||
elseif ($count == 2) {
|
||||
// 删除的话取匹配到的所有内容
|
||||
if ($remove) {
|
||||
|
@ -187,6 +142,20 @@ class Selector
|
|||
return count($result) > 1 ? $result : $result[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* css选择器
|
||||
*
|
||||
* @param $html
|
||||
* @param string $selector
|
||||
* @param bool $remove
|
||||
* @return array|string|null
|
||||
*/
|
||||
private static function _css_select($html, $selector, $remove = false)
|
||||
{
|
||||
$selector = self::css_to_xpath($selector);
|
||||
return self::_xpath_select($html, $selector, $remove);
|
||||
}
|
||||
|
||||
/**
|
||||
* CSS表达式转换为Xpath表达式
|
||||
* @param string $selectors
|
||||
|
@ -202,24 +171,21 @@ class Selector
|
|||
$is_tag = preg_match('@^[\w|\||-]+$@', $s) || $s == '*';
|
||||
if ($is_tag) {
|
||||
$xquery .= $s;
|
||||
}
|
||||
// ID
|
||||
} // ID
|
||||
elseif ($s[0] == '#') {
|
||||
if ($delimiter_before) {
|
||||
$xquery .= '*';
|
||||
}
|
||||
// ID用精确查询
|
||||
$xquery .= "[@id='" . substr($s, 1) . "']";
|
||||
}
|
||||
// CLASSES
|
||||
} // CLASSES
|
||||
elseif ($s[0] == '.') {
|
||||
if ($delimiter_before) {
|
||||
$xquery .= '*';
|
||||
}
|
||||
// CLASS用模糊查询
|
||||
$xquery .= "[contains(@class,'" . substr($s, 1) . "')]";
|
||||
}
|
||||
// ATTRIBUTES
|
||||
} // ATTRIBUTES
|
||||
elseif ($s[0] == '[') {
|
||||
if ($delimiter_before) {
|
||||
$xquery .= '*';
|
||||
|
@ -238,32 +204,25 @@ class Selector
|
|||
} else {
|
||||
$xquery .= "[@{$attr}='{$value}']";
|
||||
}
|
||||
}
|
||||
// attr without specified value
|
||||
} // attr without specified value
|
||||
else {
|
||||
$xquery .= "[@{$attr}]";
|
||||
}
|
||||
}
|
||||
// ~ General Sibling Selector
|
||||
} // ~ General Sibling Selector
|
||||
elseif ($s[0] == '~') {
|
||||
}
|
||||
// + Adjacent sibling selectors
|
||||
} // + Adjacent sibling selectors
|
||||
elseif ($s[0] == '+') {
|
||||
}
|
||||
// PSEUDO CLASSES
|
||||
} // PSEUDO CLASSES
|
||||
elseif ($s[0] == ':') {
|
||||
}
|
||||
// DIRECT DESCENDANDS
|
||||
} // DIRECT DESCENDANDS
|
||||
elseif ($s == '>') {
|
||||
$xquery .= '/';
|
||||
$delimiter_before = 2;
|
||||
}
|
||||
// ALL DESCENDANDS
|
||||
} // ALL DESCENDANDS
|
||||
elseif ($s == ' ') {
|
||||
$xquery .= '//';
|
||||
$delimiter_before = 2;
|
||||
}
|
||||
// ERRORS
|
||||
} // ERRORS
|
||||
else {
|
||||
exit("Unrecognized token '$s'");
|
||||
}
|
||||
|
@ -309,8 +268,7 @@ class Selector
|
|||
$i++;
|
||||
}
|
||||
$queries[] = $tmp;
|
||||
}
|
||||
// IDs
|
||||
} // IDs
|
||||
elseif ($c == '#') {
|
||||
$i++;
|
||||
while (isset($query[$i]) && (self::is_char($query[$i]) || $query[$i] == '-')) {
|
||||
|
@ -318,8 +276,7 @@ class Selector
|
|||
$i++;
|
||||
}
|
||||
$queries[] = '#' . $tmp;
|
||||
}
|
||||
// SPECIAL CHARS
|
||||
} // SPECIAL CHARS
|
||||
elseif (in_array($c, $special_chars)) {
|
||||
$queries[] = $c;
|
||||
$i++;
|
||||
|
@ -327,28 +284,24 @@ class Selector
|
|||
// } else if ( $c.$query[$i+1] == '//') {
|
||||
// $return[] = ' ';
|
||||
// $i = $i+2;
|
||||
}
|
||||
// MAPPED SPECIAL CHARS
|
||||
} // MAPPED SPECIAL CHARS
|
||||
elseif (isset($special_chars_mapping[$c])) {
|
||||
$queries[] = $special_chars_mapping[$c];
|
||||
$i++;
|
||||
}
|
||||
// COMMA
|
||||
} // COMMA
|
||||
elseif ($c == ',') {
|
||||
$i++;
|
||||
while (isset($query[$i]) && $query[$i] == ' ') {
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
// CLASSES
|
||||
} // CLASSES
|
||||
elseif ($c == '.') {
|
||||
while (isset($query[$i]) && (self::is_char($query[$i]) || in_array($query[$i], $class_chars))) {
|
||||
$tmp .= $query[$i];
|
||||
$i++;
|
||||
}
|
||||
$queries[] = $tmp;
|
||||
}
|
||||
// ~ General Sibling Selector
|
||||
} // ~ General Sibling Selector
|
||||
elseif ($c == '~') {
|
||||
$space_allowed = true;
|
||||
$tmp .= $query[$i++];
|
||||
|
@ -366,8 +319,7 @@ class Selector
|
|||
$i++;
|
||||
}
|
||||
$queries[] = $tmp;
|
||||
}
|
||||
// + Adjacent sibling selectors
|
||||
} // + Adjacent sibling selectors
|
||||
elseif ($c == '+') {
|
||||
$space_allowed = true;
|
||||
$tmp .= $query[$i++];
|
||||
|
@ -385,8 +337,7 @@ class Selector
|
|||
$i++;
|
||||
}
|
||||
$queries[] = $tmp;
|
||||
}
|
||||
// ATTRS
|
||||
} // ATTRS
|
||||
elseif ($c == '[') {
|
||||
$stack = 1;
|
||||
$tmp .= $c;
|
||||
|
@ -403,8 +354,7 @@ class Selector
|
|||
}
|
||||
$queries[] = $tmp;
|
||||
$i++;
|
||||
}
|
||||
// PSEUDO CLASSES
|
||||
} // PSEUDO CLASSES
|
||||
elseif ($c == ':') {
|
||||
$stack = 1;
|
||||
$tmp .= $query[$i++];
|
||||
|
@ -471,4 +421,34 @@ class Selector
|
|||
{
|
||||
return in_array($pattern[mb_strlen($pattern) - 1], array('^', '*', '$'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $html
|
||||
* @param string $selector
|
||||
* @param string $selector_type
|
||||
* @return mixed|null
|
||||
*/
|
||||
public static function remove($html, $selector, $selector_type = 'xpath')
|
||||
{
|
||||
if (empty($html) || empty($selector)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$selector_type = strtolower($selector_type);
|
||||
switch ($selector_type) {
|
||||
case 'xpath':
|
||||
$remove_html = self::_xpath_select($html, $selector, true);
|
||||
break;
|
||||
case 'regex':
|
||||
$remove_html = self::_regex_select($html, $selector, true);
|
||||
break;
|
||||
case 'css':
|
||||
$remove_html = self::_css_select($html, $selector, true);
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
return str_replace($remove_html, '', $html);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace IYUU\Library;
|
||||
|
||||
/**
|
||||
|
@ -103,23 +104,6 @@ class Table
|
|||
$this->checkColWidth($header);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置输出表格数据 及对齐方式
|
||||
* @access public
|
||||
* @param array $rows 要输出的表格数据(二维数组)
|
||||
* @param int $align 对齐方式 默认1 ALGIN_LEFT 0 ALIGN_RIGHT 2 ALIGN_CENTER
|
||||
* @return void
|
||||
*/
|
||||
public function setRows($rows, $align = self::ALIGN_LEFT)
|
||||
{
|
||||
$this->rows = $rows;
|
||||
$this->cellAlign = $align;
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$this->checkColWidth($row);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查列数据的显示宽度
|
||||
* @access public
|
||||
|
@ -155,71 +139,6 @@ class Table
|
|||
$this->checkColWidth($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置输出表格的样式
|
||||
* @access public
|
||||
* @param string $style 样式名
|
||||
* @return void
|
||||
*/
|
||||
public function setStyle($style)
|
||||
{
|
||||
$this->style = isset($this->format[$style]) ? $style : 'default';
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出分隔行
|
||||
* @access public
|
||||
* @param string $pos 位置
|
||||
* @return string
|
||||
*/
|
||||
protected function renderSeparator($pos)
|
||||
{
|
||||
$style = $this->getStyle($pos);
|
||||
$array = [];
|
||||
|
||||
foreach ($this->colWidth as $width) {
|
||||
$array[] = str_repeat($style[1], $width + 2);
|
||||
}
|
||||
|
||||
return $style[0] . implode($style[2], $array) . $style[3] . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出表格头部
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
protected function renderHeader()
|
||||
{
|
||||
$style = $this->getStyle('cell');
|
||||
$content = $this->renderSeparator('top');
|
||||
|
||||
foreach ($this->header as $key => $header) {
|
||||
$array[] = ' ' . str_pad($header, $this->colWidth[$key], $style[1], $this->headerAlign);
|
||||
}
|
||||
|
||||
if (!empty($array)) {
|
||||
$content .= $style[0] . implode(' ' . $style[2], $array) . ' ' . $style[3] . PHP_EOL;
|
||||
|
||||
if ($this->rows) {
|
||||
$content .= $this->renderSeparator('middle');
|
||||
}
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
protected function getStyle($style)
|
||||
{
|
||||
if ($this->format[$this->style]) {
|
||||
$style = $this->format[$this->style][$style];
|
||||
} else {
|
||||
$style = [' ', ' ', ' ', ' '];
|
||||
}
|
||||
|
||||
return $style;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出表格
|
||||
* @access public
|
||||
|
@ -264,4 +183,86 @@ class Table
|
|||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置输出表格数据 及对齐方式
|
||||
* @access public
|
||||
* @param array $rows 要输出的表格数据(二维数组)
|
||||
* @param int $align 对齐方式 默认1 ALGIN_LEFT 0 ALIGN_RIGHT 2 ALIGN_CENTER
|
||||
* @return void
|
||||
*/
|
||||
public function setRows($rows, $align = self::ALIGN_LEFT)
|
||||
{
|
||||
$this->rows = $rows;
|
||||
$this->cellAlign = $align;
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$this->checkColWidth($row);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出表格头部
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
protected function renderHeader()
|
||||
{
|
||||
$style = $this->getStyle('cell');
|
||||
$content = $this->renderSeparator('top');
|
||||
|
||||
foreach ($this->header as $key => $header) {
|
||||
$array[] = ' ' . str_pad($header, $this->colWidth[$key], $style[1], $this->headerAlign);
|
||||
}
|
||||
|
||||
if (!empty($array)) {
|
||||
$content .= $style[0] . implode(' ' . $style[2], $array) . ' ' . $style[3] . PHP_EOL;
|
||||
|
||||
if ($this->rows) {
|
||||
$content .= $this->renderSeparator('middle');
|
||||
}
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
protected function getStyle($style)
|
||||
{
|
||||
if ($this->format[$this->style]) {
|
||||
$style = $this->format[$this->style][$style];
|
||||
} else {
|
||||
$style = [' ', ' ', ' ', ' '];
|
||||
}
|
||||
|
||||
return $style;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置输出表格的样式
|
||||
* @access public
|
||||
* @param string $style 样式名
|
||||
* @return void
|
||||
*/
|
||||
public function setStyle($style)
|
||||
{
|
||||
$this->style = isset($this->format[$style]) ? $style : 'default';
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出分隔行
|
||||
* @access public
|
||||
* @param string $pos 位置
|
||||
* @return string
|
||||
*/
|
||||
protected function renderSeparator($pos)
|
||||
{
|
||||
$style = $this->getStyle($pos);
|
||||
$array = [];
|
||||
|
||||
foreach ($this->colWidth as $width) {
|
||||
$array[] = str_repeat($style[1], $width + 2);
|
||||
}
|
||||
|
||||
return $style[0] . implode($style[2], $array) . $style[3] . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace IYUU\Reseed;
|
||||
|
||||
use Curl\Curl;
|
||||
|
@ -19,41 +20,6 @@ use app\domain\Crontab as domainCrontab;
|
|||
*/
|
||||
class AutoReseed
|
||||
{
|
||||
/**
|
||||
* 解析的运行时配置
|
||||
* @var array
|
||||
*/
|
||||
protected static $conf = [];
|
||||
/**
|
||||
* RPC连接
|
||||
* @var array
|
||||
*/
|
||||
protected static $links = [];
|
||||
/**
|
||||
* 客户端
|
||||
* @var array
|
||||
*/
|
||||
protected static $clients = [];
|
||||
/**
|
||||
* 站点
|
||||
* @var array
|
||||
*/
|
||||
private static $sites = [];
|
||||
/**
|
||||
* 用户选择辅种的站点
|
||||
* @var array
|
||||
*/
|
||||
private static $_sites = [];
|
||||
/**
|
||||
* 推荐的合作站点
|
||||
* @var array
|
||||
*/
|
||||
private static $recommend = [];
|
||||
/**
|
||||
* 不辅种的站点
|
||||
* @var array
|
||||
*/
|
||||
private static $noReseed = [];
|
||||
/**
|
||||
* 运行缓存目录
|
||||
* @var string
|
||||
|
@ -74,6 +40,26 @@ class AutoReseed
|
|||
* @var string
|
||||
*/
|
||||
public static $cacheNotify = TORRENT_PATH . DIRECTORY_SEPARATOR . 'cacheNotify' . DIRECTORY_SEPARATOR;
|
||||
/**
|
||||
* 退出状态码
|
||||
* @var int
|
||||
*/
|
||||
public static $ExitCode = 0;
|
||||
/**
|
||||
* 解析的运行时配置
|
||||
* @var array
|
||||
*/
|
||||
protected static $conf = [];
|
||||
/**
|
||||
* RPC连接
|
||||
* @var array
|
||||
*/
|
||||
protected static $links = [];
|
||||
/**
|
||||
* 客户端
|
||||
* @var array
|
||||
*/
|
||||
protected static $clients = [];
|
||||
/**
|
||||
* @var null | Curl
|
||||
*/
|
||||
|
@ -83,11 +69,6 @@ class AutoReseed
|
|||
* @var string
|
||||
*/
|
||||
protected static $pid_file = '';
|
||||
/**
|
||||
* 退出状态码
|
||||
* @var int
|
||||
*/
|
||||
public static $ExitCode = 0;
|
||||
/**
|
||||
* 微信通知消息体
|
||||
* @var array
|
||||
|
@ -115,11 +96,30 @@ class AutoReseed
|
|||
'torrent_id' => 0,
|
||||
'error' => '',
|
||||
);
|
||||
|
||||
/**
|
||||
* 临时变量
|
||||
*/
|
||||
protected static $temp = [];
|
||||
/**
|
||||
* 站点
|
||||
* @var array
|
||||
*/
|
||||
private static $sites = [];
|
||||
/**
|
||||
* 用户选择辅种的站点
|
||||
* @var array
|
||||
*/
|
||||
private static $_sites = [];
|
||||
/**
|
||||
* 推荐的合作站点
|
||||
* @var array
|
||||
*/
|
||||
private static $recommend = [];
|
||||
/**
|
||||
* 不辅种的站点
|
||||
* @var array
|
||||
*/
|
||||
private static $noReseed = [];
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
|
@ -187,7 +187,7 @@ class AutoReseed
|
|||
* 保存进程pid文件
|
||||
* @param string $cron_name
|
||||
*/
|
||||
protected static function savePid($cron_name = '')
|
||||
protected static function savePid(string $cron_name = '')
|
||||
{
|
||||
self::$conf['cron_name'] = $cron_name; // 保存计划任务名字
|
||||
//pid文件
|
||||
|
@ -347,91 +347,6 @@ class AutoReseed
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 添加下载任务
|
||||
* @param $clientKey
|
||||
* @param string $torrent 种子元数据
|
||||
* @param string $save_path 保存路径
|
||||
* @param array $extra_options
|
||||
* @return bool
|
||||
*/
|
||||
protected static function add($clientKey, $torrent, $save_path = '', $extra_options = array())
|
||||
{
|
||||
try {
|
||||
$is_url = static::isTorrentUrl($torrent);
|
||||
// 下载服务器类型
|
||||
$type = static::$links[$clientKey]['type'];
|
||||
// 判断
|
||||
switch ($type) {
|
||||
case 'transmission':
|
||||
$extra_options['paused'] = isset($extra_options['paused']) ? $extra_options['paused'] : true;
|
||||
if ($is_url) {
|
||||
$result = static::getRpc($clientKey)->add($torrent, $save_path, $extra_options); // URL添加
|
||||
} else {
|
||||
$result = static::getRpc($clientKey)->add_metainfo($torrent, $save_path, $extra_options); // 元数据添加
|
||||
}
|
||||
if (isset($result['result']) && $result['result'] == 'success') {
|
||||
$_key = isset($result['arguments']['torrent-added']) ? 'torrent-added' : 'torrent-duplicate';
|
||||
$id = $result['arguments'][$_key]['id'];
|
||||
$name = $result['arguments'][$_key]['name'];
|
||||
print "名字:" .$name . PHP_EOL;
|
||||
print "********RPC添加下载任务成功 [" .$result['result']. "] (id=" .$id. ")".PHP_EOL.PHP_EOL;
|
||||
return true;
|
||||
} else {
|
||||
$err = isset($result['result']) ? $result['result'] : '未知错误,请稍后重试!';
|
||||
if (strpos($err, 'http error 404: Not Found') !== false) {
|
||||
static::sendNotify('404');
|
||||
}
|
||||
print "-----RPC添加种子任务,失败 [{$err}]" . PHP_EOL.PHP_EOL;
|
||||
}
|
||||
break;
|
||||
case 'qBittorrent':
|
||||
//如果用户的下载器设置自动种子管理,需要传入这个参数
|
||||
if (isset(static::$links[$clientKey]['_config']['autoTMM'])) {
|
||||
$extra_options['autoTMM'] = 'false'; //关闭自动种子管理
|
||||
}
|
||||
// 添加任务校验后是否暂停
|
||||
if (isset($extra_options['paused'])) {
|
||||
$extra_options['paused'] = $extra_options['paused'] ? 'true' : 'false';
|
||||
} else {
|
||||
$extra_options['paused'] = 'true';
|
||||
}
|
||||
// 是否创建根目录
|
||||
$extra_options['root_folder'] = static::$links[$clientKey]['root_folder'] ? 'true' : 'false';
|
||||
if ($is_url) {
|
||||
$result = static::getRpc($clientKey)->add($torrent, $save_path, $extra_options); // URL添加
|
||||
} else {
|
||||
$extra_options['name'] = 'torrents';
|
||||
$extra_options['filename'] = time().'.torrent';
|
||||
$result = static::getRpc($clientKey)->add_metainfo($torrent, $save_path, $extra_options); // 元数据添加
|
||||
}
|
||||
if ($result === 'Ok.') {
|
||||
print "********RPC添加下载任务成功 [{$result}]".PHP_EOL.PHP_EOL;
|
||||
return true;
|
||||
} else {
|
||||
print "-----RPC添加种子任务,失败 [{$result}]".PHP_EOL.PHP_EOL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
echo '[下载器类型错误] '.$type. PHP_EOL. PHP_EOL;
|
||||
break;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo '[添加下载任务出错] ' . $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断内容是否为种子的URL链接
|
||||
* @param string $torrent
|
||||
* @return bool
|
||||
*/
|
||||
protected static function isTorrentUrl(string $torrent)
|
||||
{
|
||||
return (stripos($torrent, 'http://') === 0) || (stripos($torrent, 'https://') === 0) || (strpos($torrent, 'magnet:?xt=urn:btih:') === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 辅种或转移,总入口
|
||||
* @throws ClientException
|
||||
|
@ -512,13 +427,29 @@ class AutoReseed
|
|||
}
|
||||
|
||||
/**
|
||||
* 优化IDE跟踪
|
||||
* @param string $clientKey
|
||||
* @return qBittorrent|transmission
|
||||
* 追加式写入日志
|
||||
* @param string|int|array|object $data
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
* @return bool|int
|
||||
*/
|
||||
public static function getRpc(string $clientKey)
|
||||
protected static function wLog($data, string $name = '', string $path = '')
|
||||
{
|
||||
return static::$links[$clientKey]['rpc'];
|
||||
if (is_bool($data)) {
|
||||
$show_data = $data ? 'true' : 'false';
|
||||
} elseif (is_null($data)) {
|
||||
$show_data = 'null';
|
||||
} else {
|
||||
$show_data = print_r($data, true);
|
||||
}
|
||||
// 写入日志
|
||||
$dir = empty($path) ? static::$cacheDir : $path;
|
||||
IFile::mkdir($dir);
|
||||
$file = $dir . $name . '.txt';
|
||||
$pointer = @fopen($file, "a");
|
||||
$result = @fwrite($pointer, $show_data);
|
||||
@fclose($pointer);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -649,7 +580,7 @@ class AutoReseed
|
|||
$reseedPass = true;
|
||||
|
||||
echo "当前站点触发人机验证,已加入流控列表" . PHP_EOL;
|
||||
self::ff($siteName. '站点,辅种时触发人机验证!');
|
||||
self::ff($siteName . '站点,辅种时触发流量控制!');
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -715,8 +646,8 @@ class AutoReseed
|
|||
$download_page = str_replace($remove, '', self::$sites[$sid]['download_page']) . str_replace('&', '&', $matchs[1]);
|
||||
$_url = $protocol . self::$sites[$sid]['base_url'] . '/' . $download_page;
|
||||
print "下载种子:" . $_url . PHP_EOL;
|
||||
$url = download($_url, $cookie, $userAgent);
|
||||
if (strpos($url, '第一次下载提示') != false) {
|
||||
$url = download($_url, $cookie, $userAgent, 'POST');
|
||||
if (strpos($url, '第一次下载提示')) {
|
||||
self::$noReseed[] = $siteName;
|
||||
$reseedPass = true;
|
||||
|
||||
|
@ -731,7 +662,18 @@ class AutoReseed
|
|||
}
|
||||
break;
|
||||
default:
|
||||
// 默认站点:推送给下载器种子URL链接
|
||||
// 未特殊定义,凭借cookie下载种子的站点
|
||||
print "下载种子:" . $_url . PHP_EOL;
|
||||
$url = download($_url, $cookie, $userAgent);
|
||||
if (strpos($url, '第一次下载提示')) {
|
||||
self::$noReseed[] = $siteName;
|
||||
$reseedPass = true;
|
||||
|
||||
echo "当前站点触发第一次下载提示,已加入排除列表" . PHP_EOL;
|
||||
echo "请进入种子详情页,下载种子,成功后更新cookie!" . PHP_EOL;
|
||||
sleepIYUU(30, '请进入种子详情页,下载种子,成功后更新cookie!');
|
||||
self::ff($siteName . '站点,辅种时触发第一次下载提示!');
|
||||
}
|
||||
break;
|
||||
}
|
||||
// 检查switch内是否异常
|
||||
|
@ -780,48 +722,19 @@ class AutoReseed
|
|||
}
|
||||
|
||||
/**
|
||||
* 请求NexusPHP详情页
|
||||
* @descr 天空、瓷器、城市 个别站用到
|
||||
* @param $protocol string 协议
|
||||
* @param $torrent array 种子
|
||||
* @param $cookie string Cookie
|
||||
* @param $userAgent string UA
|
||||
* @return mixed|null
|
||||
* 设置通知主体
|
||||
* @param string $siteName
|
||||
* @param int $sid
|
||||
* @param int $torrent_id
|
||||
*/
|
||||
private static function getNexusPHPdetailsPage($protocol, $torrent, $cookie, $userAgent)
|
||||
private static function setNotify($siteName = '', $sid = 0, $torrent_id = 0)
|
||||
{
|
||||
$sid = $torrent['sid'];
|
||||
$torrent_id = $torrent['torrent_id'];
|
||||
|
||||
// 拼接详情页URL
|
||||
$details = str_replace('{}', $torrent_id, 'details.php?id={}&hit=1');
|
||||
$details_url = $protocol . self::$sites[$sid]['base_url'] . '/' .$details;
|
||||
print "种子详情页:".$details_url.PHP_EOL;
|
||||
$details_html = download($details_url, $cookie, $userAgent);
|
||||
// 删种检查
|
||||
if (strpos($details_html, '没有该ID的种子') != false) {
|
||||
echo '种子已被删除!'.PHP_EOL;
|
||||
self::sendNotify('404');
|
||||
return null;
|
||||
}
|
||||
return $details_html;
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信通知cookie失效,延时15秒提示
|
||||
* @descr 天空、瓷器、城市 个别站用到
|
||||
* @param $siteName
|
||||
*/
|
||||
private static function cookieExpired($siteName)
|
||||
{
|
||||
$msg = $siteName. '站点,cookie已过期,请更新后重新辅种!';
|
||||
$msg_md5 = md5($msg);
|
||||
if (empty(static::$temp[$msg_md5])) {
|
||||
self::ff($msg);
|
||||
static::$temp[$msg_md5] = $msg;
|
||||
}
|
||||
|
||||
sleepIYUU(15, 'cookie已过期,请更新后重新辅种!出现此提示切莫惊慌,请根据提示信息,手动访问种子详情页,检查种子是否被删除。');
|
||||
self::$errNotify = array(
|
||||
'sign' => Oauth::getSign(),
|
||||
'site' => $siteName,
|
||||
'sid' => $sid,
|
||||
'torrent_id' => $torrent_id,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -917,6 +830,68 @@ class AutoReseed
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求NexusPHP详情页
|
||||
* @descr 天空、瓷器、城市 个别站用到
|
||||
* @param $protocol string 协议
|
||||
* @param $torrent array 种子
|
||||
* @param $cookie string Cookie
|
||||
* @param $userAgent string UA
|
||||
* @return mixed|null
|
||||
*/
|
||||
private static function getNexusPHPdetailsPage($protocol, $torrent, $cookie, $userAgent)
|
||||
{
|
||||
$sid = $torrent['sid'];
|
||||
$torrent_id = $torrent['torrent_id'];
|
||||
|
||||
// 拼接详情页URL
|
||||
$details = str_replace('{}', $torrent_id, 'details.php?id={}&hit=1');
|
||||
$details_url = $protocol . self::$sites[$sid]['base_url'] . '/' . $details;
|
||||
print "种子详情页:" . $details_url . PHP_EOL;
|
||||
$details_html = download($details_url, $cookie, $userAgent);
|
||||
// 删种检查
|
||||
if (strpos($details_html, '没有该ID的种子') != false) {
|
||||
echo '种子已被删除!' . PHP_EOL;
|
||||
self::sendNotify('404');
|
||||
return null;
|
||||
}
|
||||
return $details_html;
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信通知cookie失效,延时15秒提示
|
||||
* @descr 天空、瓷器、城市 个别站用到
|
||||
* @param $siteName
|
||||
*/
|
||||
private static function cookieExpired($siteName)
|
||||
{
|
||||
$msg = $siteName . '站点,cookie已过期,请更新后重新辅种!';
|
||||
$msg_md5 = md5($msg);
|
||||
if (empty(static::$temp[$msg_md5])) {
|
||||
self::ff($msg);
|
||||
static::$temp[$msg_md5] = $msg;
|
||||
}
|
||||
|
||||
sleepIYUU(15, 'cookie已过期,请更新后重新辅种!出现此提示切莫惊慌,请根据提示信息,手动访问种子详情页,检查种子是否被删除。');
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信推送 爱语飞飞
|
||||
* @param string $text
|
||||
* @param string $desp
|
||||
* @return false|string
|
||||
*/
|
||||
protected static function ff($text = '', $desp = '')
|
||||
{
|
||||
$token = static::$conf['iyuu.cn'];
|
||||
$desp = empty($desp) ? date("Y-m-d H:i:s") : $desp;
|
||||
$data = array(
|
||||
'text' => $text,
|
||||
'desp' => $desp
|
||||
);
|
||||
return ICurl::http_post('https://iyuu.cn/' . $token . '.send', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取站点种子的URL
|
||||
* @param string $site 站点名称
|
||||
|
@ -1052,6 +1027,148 @@ class AutoReseed
|
|||
return $signString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 添加下载任务
|
||||
* @param $clientKey
|
||||
* @param string $torrent 种子元数据
|
||||
* @param string $save_path 保存路径
|
||||
* @param array $extra_options
|
||||
* @return bool
|
||||
*/
|
||||
protected static function add($clientKey, $torrent, $save_path = '', $extra_options = array())
|
||||
{
|
||||
try {
|
||||
$is_url = static::isTorrentUrl($torrent);
|
||||
// 下载服务器类型
|
||||
$type = static::$links[$clientKey]['type'];
|
||||
// 判断
|
||||
switch ($type) {
|
||||
case 'transmission':
|
||||
$extra_options['paused'] = isset($extra_options['paused']) ? $extra_options['paused'] : true;
|
||||
if ($is_url) {
|
||||
$result = static::getRpc($clientKey)->add($torrent, $save_path, $extra_options); // URL添加
|
||||
} else {
|
||||
$result = static::getRpc($clientKey)->add_metainfo($torrent, $save_path, $extra_options); // 元数据添加
|
||||
}
|
||||
if (isset($result['result']) && $result['result'] == 'success') {
|
||||
$_key = isset($result['arguments']['torrent-added']) ? 'torrent-added' : 'torrent-duplicate';
|
||||
$id = $result['arguments'][$_key]['id'];
|
||||
$name = $result['arguments'][$_key]['name'];
|
||||
print "名字:" . $name . PHP_EOL;
|
||||
print "********RPC添加下载任务成功 [" . $result['result'] . "] (id=" . $id . ")" . PHP_EOL . PHP_EOL;
|
||||
return true;
|
||||
} else {
|
||||
$err = isset($result['result']) ? $result['result'] : '未知错误,请稍后重试!';
|
||||
if (strpos($err, 'http error 404: Not Found') !== false) {
|
||||
static::sendNotify('404');
|
||||
}
|
||||
print "-----RPC添加种子任务,失败 [{$err}]" . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
break;
|
||||
case 'qBittorrent':
|
||||
//如果用户的下载器设置自动种子管理,需要传入这个参数
|
||||
if (isset(static::$links[$clientKey]['_config']['autoTMM'])) {
|
||||
$extra_options['autoTMM'] = 'false'; //关闭自动种子管理
|
||||
}
|
||||
// 添加任务校验后是否暂停
|
||||
if (isset($extra_options['paused'])) {
|
||||
$extra_options['paused'] = $extra_options['paused'] ? 'true' : 'false';
|
||||
} else {
|
||||
$extra_options['paused'] = 'true';
|
||||
}
|
||||
// 是否创建根目录
|
||||
$extra_options['root_folder'] = static::$links[$clientKey]['root_folder'] ? 'true' : 'false';
|
||||
if ($is_url) {
|
||||
$result = static::getRpc($clientKey)->add($torrent, $save_path, $extra_options); // URL添加
|
||||
} else {
|
||||
$extra_options['name'] = 'torrents';
|
||||
$extra_options['filename'] = time() . '.torrent';
|
||||
$result = static::getRpc($clientKey)->add_metainfo($torrent, $save_path, $extra_options); // 元数据添加
|
||||
}
|
||||
if ($result === 'Ok.') {
|
||||
print "********RPC添加下载任务成功 [{$result}]" . PHP_EOL . PHP_EOL;
|
||||
return true;
|
||||
} else {
|
||||
print "-----RPC添加种子任务,失败 [{$result}]" . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
echo '[下载器类型错误] ' . $type . PHP_EOL . PHP_EOL;
|
||||
break;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo '[添加下载任务出错] ' . $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断内容是否为种子的URL链接
|
||||
* @param string $torrent
|
||||
* @return bool
|
||||
*/
|
||||
protected static function isTorrentUrl(string $torrent)
|
||||
{
|
||||
return (stripos($torrent, 'http://') === 0) || (stripos($torrent, 'https://') === 0) || (strpos($torrent, 'magnet:?xt=urn:btih:') === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 优化IDE跟踪
|
||||
* @param string $clientKey
|
||||
* @return qBittorrent|transmission
|
||||
*/
|
||||
public static function getRpc(string $clientKey)
|
||||
{
|
||||
return static::$links[$clientKey]['rpc'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误的种子通知服务器
|
||||
* @param string $error
|
||||
* @return bool
|
||||
*/
|
||||
private static function sendNotify($error = '')
|
||||
{
|
||||
self::$errNotify['error'] = $error;
|
||||
|
||||
// 存在错误通知缓存,直接返回(减少请求次数)
|
||||
$errNotifyCacheFile = self::errNotifyCacheFile(self::$errNotify['sid'], self::$errNotify['torrent_id']);
|
||||
if (is_file($errNotifyCacheFile)) {
|
||||
echo '感谢您的参与,失效种子已经成功汇报过!!' . PHP_EOL;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 创建错误通知缓存
|
||||
file_put_contents($errNotifyCacheFile, json_encode(self::$errNotify, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$notify = http_build_query(self::$errNotify);
|
||||
self::$errNotify = array(
|
||||
'sign' => '',
|
||||
'site' => '',
|
||||
'sid' => 0,
|
||||
'torrent_id' => 0,
|
||||
'error' => '',
|
||||
);
|
||||
$res = self::$curl->get(Constant::API_BASE . Constant::API['notify'] . '?' . $notify);
|
||||
$res = json_decode($res->response, true);
|
||||
if (isset($res['data']['success']) && $res['data']['success']) {
|
||||
echo '感谢您的参与,失效种子上报成功!!' . PHP_EOL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接错误通知缓存的文件路径
|
||||
* @param int $site_id
|
||||
* @param int $torrent_id
|
||||
* @return string
|
||||
*/
|
||||
private static function errNotifyCacheFile($site_id = 0, $torrent_id = 0)
|
||||
{
|
||||
$filename = $site_id . '_' . $torrent_id . '.txt';
|
||||
return self::$cacheNotify . $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信模板消息拼接方法
|
||||
* @return string 发送情况,json
|
||||
|
@ -1106,110 +1223,4 @@ class AutoReseed
|
|||
$desp .= $br . '*此消息将在3天后过期*。';
|
||||
return self::ff($text, $desp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误的种子通知服务器
|
||||
* @param string $error
|
||||
* @return bool
|
||||
*/
|
||||
private static function sendNotify($error = '')
|
||||
{
|
||||
self::$errNotify['error'] = $error;
|
||||
|
||||
// 存在错误通知缓存,直接返回(减少请求次数)
|
||||
$errNotifyCacheFile = self::errNotifyCacheFile(self::$errNotify['sid'], self::$errNotify['torrent_id']);
|
||||
if (is_file($errNotifyCacheFile)) {
|
||||
echo '感谢您的参与,失效种子已经成功汇报过!!'.PHP_EOL;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 创建错误通知缓存
|
||||
file_put_contents($errNotifyCacheFile, json_encode(self::$errNotify, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$notify = http_build_query(self::$errNotify);
|
||||
self::$errNotify = array(
|
||||
'sign' => '',
|
||||
'site' => '',
|
||||
'sid' => 0,
|
||||
'torrent_id'=> 0,
|
||||
'error' => '',
|
||||
);
|
||||
$res = self::$curl->get(Constant::API_BASE . Constant::API['notify'] . '?' . $notify);
|
||||
$res = json_decode($res->response, true);
|
||||
if (isset($res['data']['success']) && $res['data']['success']) {
|
||||
echo '感谢您的参与,失效种子上报成功!!'.PHP_EOL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接错误通知缓存的文件路径
|
||||
* @param int $site_id
|
||||
* @param int $torrent_id
|
||||
* @return string
|
||||
*/
|
||||
private static function errNotifyCacheFile($site_id = 0, $torrent_id = 0)
|
||||
{
|
||||
$filename = $site_id . '_' . $torrent_id . '.txt';
|
||||
return self::$cacheNotify . $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置通知主体
|
||||
* @param string $siteName
|
||||
* @param int $sid
|
||||
* @param int $torrent_id
|
||||
*/
|
||||
private static function setNotify($siteName = '', $sid = 0, $torrent_id = 0)
|
||||
{
|
||||
self::$errNotify = array(
|
||||
'sign' => Oauth::getSign(),
|
||||
'site' => $siteName,
|
||||
'sid' => $sid,
|
||||
'torrent_id'=> $torrent_id,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信推送 爱语飞飞
|
||||
* @param string $text
|
||||
* @param string $desp
|
||||
* @return false|string
|
||||
*/
|
||||
protected static function ff($text='', $desp='')
|
||||
{
|
||||
$token = static::$conf['iyuu.cn'];
|
||||
$desp = empty($desp) ? date("Y-m-d H:i:s") : $desp;
|
||||
$data = array(
|
||||
'text' => $text,
|
||||
'desp' => $desp
|
||||
);
|
||||
return ICurl::http_post('https://iyuu.cn/'.$token.'.send', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 追加式写入日志
|
||||
* @param string|int|array|object $data
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
* @return bool|int
|
||||
*/
|
||||
protected static function wLog($data, string $name = '', string $path = '')
|
||||
{
|
||||
if (is_bool($data)) {
|
||||
$show_data = $data ? 'true' : 'false';
|
||||
} elseif (is_null($data)) {
|
||||
$show_data = 'null';
|
||||
} else {
|
||||
$show_data = print_r($data, true);
|
||||
}
|
||||
// 写入日志
|
||||
$dir = empty($path) ? static::$cacheDir : $path;
|
||||
IFile::mkdir($dir);
|
||||
$file = $dir . $name . '.txt';
|
||||
$pointer = @fopen($file, "a");
|
||||
$result = @fwrite($pointer, $show_data);
|
||||
@fclose($pointer);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace IYUU\Reseed;
|
||||
|
||||
use app\domain\ConfigParser\Move as domainMove;
|
||||
|
@ -32,6 +33,7 @@ class MoveTorrent extends AutoReseed
|
|||
'MoveSuccess' => 0, // 移动成功
|
||||
'MoveError' => 0, // 移动失败
|
||||
);
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
|
@ -172,7 +174,8 @@ class MoveTorrent extends AutoReseed
|
|||
if (empty($parsed_torrent['announce'])) {
|
||||
$needPatchTorrent = true;
|
||||
}
|
||||
} catch (ParseException $e) {}
|
||||
} catch (ParseException $e) {
|
||||
}
|
||||
if ($needPatchTorrent) {
|
||||
echo '未发现tracker信息,尝试补充tracker信息...' . PHP_EOL;
|
||||
if (empty($parsed_torrent)) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace IYUU\Reseed;
|
||||
|
||||
use Curl\Curl;
|
||||
|
@ -8,9 +9,9 @@ use Curl\Curl;
|
|||
*/
|
||||
class Oauth
|
||||
{
|
||||
private static $conf = [];
|
||||
// 登录缓存路径
|
||||
const SiteLoginCache = RUNTIME_PATH . DS . 'db' . DS . 'siteLoginCache_{}.json';
|
||||
// 登录缓存路径
|
||||
private static $conf = [];
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
|
@ -23,20 +24,6 @@ class Oauth
|
|||
self::$conf = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从配置文件内读取爱语飞飞token作为鉴权参数
|
||||
*/
|
||||
public static function getSign()
|
||||
{
|
||||
$token = empty(self::$conf['iyuu.cn']) ? '' : self::$conf['iyuu.cn'];
|
||||
if (empty($token) || strlen($token) < 46) {
|
||||
echo "缺少辅种接口请求参数:爱语飞飞token ".PHP_EOL;
|
||||
echo "请访问https://iyuu.cn 用微信扫码申请。".PHP_EOL.PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户注册与登录
|
||||
* 作用:在服务器端实现微信用户与合作站点用户id的关联
|
||||
|
@ -92,6 +79,20 @@ class Oauth
|
|||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从配置文件内读取爱语飞飞token作为鉴权参数
|
||||
*/
|
||||
public static function getSign()
|
||||
{
|
||||
$token = empty(self::$conf['iyuu.cn']) ? '' : self::$conf['iyuu.cn'];
|
||||
if (empty($token) || strlen($token) < 46) {
|
||||
echo "缺少辅种接口请求参数:爱语飞飞token " . PHP_EOL;
|
||||
echo "请访问https://iyuu.cn 用微信扫码申请。" . PHP_EOL . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写鉴权成功缓存
|
||||
* @desc 作用:减少对服务器请求,跳过鉴权提示信息;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
use DOMDocument;
|
||||
|
@ -10,11 +11,25 @@ use app\domain\ConfigParser\Rss as domainRss;
|
|||
|
||||
abstract class AbstractRss
|
||||
{
|
||||
const encoding = 'UTF-8';
|
||||
const CONNECTTIMEOUT = 30;
|
||||
const TIMEOUT = 600;
|
||||
/**
|
||||
* 站点名转换为文件名,所使用的映射表
|
||||
*/
|
||||
const SITENAME_TO_FILENAME_MAP = Constant::SITENAME_TO_FILENAME_MAP;
|
||||
/**
|
||||
* 运行时解析的配置
|
||||
* @var array
|
||||
*/
|
||||
protected static $conf = [];
|
||||
// 网页编码
|
||||
/**
|
||||
* 站点标志
|
||||
* @var string
|
||||
*/
|
||||
public $site = '';
|
||||
// 超时时间
|
||||
/**
|
||||
* 域名
|
||||
* @var string
|
||||
|
@ -32,11 +47,6 @@ abstract class AbstractRss
|
|||
* RSS订阅的默认页面
|
||||
*/
|
||||
public $rss_page = 'torrentrss.php?rows=50&linktype=dl&passkey={}';
|
||||
// 网页编码
|
||||
const encoding = 'UTF-8';
|
||||
// 超时时间
|
||||
const CONNECTTIMEOUT = 30;
|
||||
const TIMEOUT = 600;
|
||||
/**
|
||||
* curl
|
||||
* @var Curl
|
||||
|
@ -46,7 +56,6 @@ abstract class AbstractRss
|
|||
* passkey
|
||||
*/
|
||||
public $passkey = '';
|
||||
|
||||
/**
|
||||
* 种子ID正则
|
||||
* @var string
|
||||
|
@ -54,15 +63,75 @@ abstract class AbstractRss
|
|||
public $torrent_id_regex = '/id=(\d+)/i';
|
||||
|
||||
/**
|
||||
* 运行时解析的配置
|
||||
* @var array
|
||||
* 构造方法,配置应用信息
|
||||
* @param bool $init 是否初始化(domainRss获取全部站点名时候,需要到)
|
||||
*/
|
||||
protected static $conf = [];
|
||||
final public function __construct($init = true)
|
||||
{
|
||||
if ($init) {
|
||||
echo $this->site . " 正在初始化RSS配置..." . PHP_EOL;
|
||||
//cli(self::$conf);
|
||||
$this->_initialize();
|
||||
$this->init();
|
||||
echo $this->site . " RSS解码类实例化,成功!" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 站点名转换为文件名,所使用的映射表
|
||||
* 初始化 第一步,初始化父类的关键参数
|
||||
*/
|
||||
const SITENAME_TO_FILENAME_MAP = Constant::SITENAME_TO_FILENAME_MAP;
|
||||
final protected function _initialize()
|
||||
{
|
||||
//云端下发
|
||||
$this->host = static::getHost(); // 示例:https://baidu.com/
|
||||
|
||||
// 初始化curl
|
||||
$this->curl = new Curl();
|
||||
$this->curl->setOpt(CURLOPT_SSL_VERIFYPEER, false); // 禁止验证对等证书
|
||||
//$this->curl->setOpt(CURLOPT_SSL_VERIFYHOST, 2); // 检查证书
|
||||
$this->curl->setOpt(CURLOPT_CONNECTTIMEOUT, self::CONNECTTIMEOUT); // 超时
|
||||
$this->curl->setOpt(CURLOPT_TIMEOUT, self::TIMEOUT); // 超时
|
||||
$this->curl->setOpt(CURLOPT_FOLLOWLOCATION, 1); // 自动跳转,跟随请求Location
|
||||
$this->curl->setOpt(CURLOPT_MAXREDIRS, 2); // 递归次数
|
||||
$this->curl->setUserAgent(static::getUserAgent());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得当前站点HOST
|
||||
* @return string
|
||||
*/
|
||||
protected static function getHost(): string
|
||||
{
|
||||
//站点配置
|
||||
$sites = static::$conf['sites'];
|
||||
$protocol = isset($sites['is_https']) && ($sites['is_https'] === 0) ? 'http://' : 'https://';
|
||||
$domain = $sites['base_url'];
|
||||
return $protocol . $domain . '/'; // 示例:https://baidu.com/
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得用户浏览器UA
|
||||
* @return string
|
||||
*/
|
||||
protected static function getUserAgent(): string
|
||||
{
|
||||
//常规配置
|
||||
$default = empty(static::$conf['default']) ? [] : static::$conf['default'];
|
||||
return !empty($default['ua']) ? $default['ua'] : Constant::UserAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 第二步,子类可以重写此方法
|
||||
*/
|
||||
protected function init()
|
||||
{
|
||||
//站点配置
|
||||
$config = static::$conf['site'];
|
||||
$this->passkey = !empty($config['passkey']) ? $config['passkey'] : '';
|
||||
if (empty($this->passkey)) {
|
||||
die($this->site . ' 没有配置密钥,初始化错误。' . PHP_EOL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 实例化
|
||||
|
@ -140,65 +209,127 @@ abstract class AbstractRss
|
|||
}
|
||||
|
||||
/**
|
||||
* 构造方法,配置应用信息
|
||||
* @param bool $init 是否初始化(domainRss获取全部站点名时候,需要到)
|
||||
* 获取配置
|
||||
* @param null $key 配置键值
|
||||
* @param null $default 默认
|
||||
* @return array|mixed|null
|
||||
*/
|
||||
final public function __construct($init = true)
|
||||
public static function getConfig($key = null, $default = null)
|
||||
{
|
||||
if ($init) {
|
||||
echo $this->site." 正在初始化RSS配置...". PHP_EOL;
|
||||
//cli(self::$conf);
|
||||
$this->_initialize();
|
||||
$this->init();
|
||||
echo $this->site." RSS解码类实例化,成功!".PHP_EOL;
|
||||
if ($key === null) {
|
||||
return self::$conf;
|
||||
}
|
||||
$key_array = \explode('.', $key);
|
||||
$value = self::$conf;
|
||||
foreach ($key_array as $index) {
|
||||
if (!isset($value[$index])) {
|
||||
return $default;
|
||||
}
|
||||
$value = $value[$index];
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 公共方法:实现rss订阅下载,子类可以重写此方法
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
echo "正在初始化RPC链接..." . PHP_EOL;
|
||||
Rpc::init($this->site, static::getTorrentDownloadMethod($this->site), self::$conf);
|
||||
$html = $this->get();
|
||||
#cli($html);
|
||||
$this->checkCallback($html);
|
||||
$data = $this->decode($html);
|
||||
echo "已解码,正在推送给RPC下载器..." . PHP_EOL;
|
||||
//cli($data);exit;
|
||||
Rpc::call($data);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取站点下载种子时使用的方法(post/get)
|
||||
* @param string $site_name
|
||||
* @return string
|
||||
*/
|
||||
public static function getTorrentDownloadMethod(string $site_name): string
|
||||
{
|
||||
$method = Constant::SITE_DOWNLOAD_METHOD_POST;
|
||||
return in_array($site_name, $method) ? 'POST' : 'GET';
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求url,获取html页面,子类可以重写此方法
|
||||
* @return string
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
if (!empty(static::$conf['urladdress'])) {
|
||||
$url = static::$conf['urladdress'];
|
||||
} else {
|
||||
$url = $this->rss_page;
|
||||
}
|
||||
if (empty($url)) {
|
||||
die('缺少 rss.page 配置');
|
||||
}
|
||||
$url = str_replace("{}", $this->passkey, $url);
|
||||
echo $this->site . " 正在请求RSS... {$url}" . PHP_EOL;
|
||||
$url = (stripos($url, 'http://') === 0 || stripos($url, 'https://') === 0) ? $url : $this->host . $url;
|
||||
$res = $this->curl->get($url);
|
||||
//cli($res);exit;
|
||||
if ($res->http_status_code == 200) {
|
||||
echo "RSS获取信息,成功!" . PHP_EOL;
|
||||
return $res->response;
|
||||
}
|
||||
echo "RSS获取信息失败,请重试!" . PHP_EOL;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调函数,子类可以重写此方法
|
||||
* @param string $html
|
||||
*/
|
||||
public function checkCallback($html = '')
|
||||
{
|
||||
if (strpos((string)$html, 'invalid passkey') !== false) {
|
||||
die('passkey填写错误,请重新填写!');
|
||||
}
|
||||
if (is_null($html)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 第一步,初始化父类的关键参数
|
||||
* 抽象方法,在子类中实现
|
||||
* 解码html为种子数组
|
||||
* @param string $html
|
||||
* @return array
|
||||
* 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时<br />46分
|
||||
* )
|
||||
* [comments] => 0
|
||||
* [size] => 5232.64MB
|
||||
* [seeders] => 69
|
||||
* [leechers] => 10
|
||||
* [completed] => 93
|
||||
* [percentage] => 100%
|
||||
* [owner] => 匿名
|
||||
* )
|
||||
*/
|
||||
final protected function _initialize()
|
||||
{
|
||||
//云端下发
|
||||
$this->host = static::getHost(); // 示例:https://baidu.com/
|
||||
|
||||
// 初始化curl
|
||||
$this->curl = new Curl();
|
||||
$this->curl->setOpt(CURLOPT_SSL_VERIFYPEER, false); // 禁止验证对等证书
|
||||
//$this->curl->setOpt(CURLOPT_SSL_VERIFYHOST, 2); // 检查证书
|
||||
$this->curl->setOpt(CURLOPT_CONNECTTIMEOUT, self::CONNECTTIMEOUT); // 超时
|
||||
$this->curl->setOpt(CURLOPT_TIMEOUT, self::TIMEOUT); // 超时
|
||||
$this->curl->setOpt(CURLOPT_FOLLOWLOCATION, 1); // 自动跳转,跟随请求Location
|
||||
$this->curl->setOpt(CURLOPT_MAXREDIRS, 2); // 递归次数
|
||||
$this->curl->setUserAgent(static::getUserAgent());
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 第二步,子类可以重写此方法
|
||||
*/
|
||||
protected function init()
|
||||
{
|
||||
//站点配置
|
||||
$config = static::$conf['site'];
|
||||
$this->passkey = !empty($config['passkey']) ? $config['passkey'] : '';
|
||||
if (empty($this->passkey)) {
|
||||
die($this->site.' 没有配置密钥,初始化错误。'.PHP_EOL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤XML文档中不需要的元素,子类可以重写此方法
|
||||
* @param DOMDocument $item
|
||||
* @return DOMDocument | DOMNode
|
||||
*/
|
||||
protected function filterNexusPHP($item)
|
||||
{
|
||||
$node = $item->getElementsByTagName('description')->item(0);
|
||||
if ($node != null) {
|
||||
$item->removeChild($node);
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
abstract public function decode($html = '');
|
||||
|
||||
/**
|
||||
* NexusPHP通用RSS解码,子类可以重写此方法
|
||||
|
@ -246,149 +377,16 @@ abstract class AbstractRss
|
|||
}
|
||||
|
||||
/**
|
||||
* 取站点下载种子时使用的方法(post/get)
|
||||
* @param string $site_name
|
||||
* @return string
|
||||
* 过滤XML文档中不需要的元素,子类可以重写此方法
|
||||
* @param DOMDocument $item
|
||||
* @return DOMDocument | DOMNode
|
||||
*/
|
||||
public static function getTorrentDownloadMethod(string $site_name):string
|
||||
protected function filterNexusPHP($item)
|
||||
{
|
||||
$method = Constant::SITE_DOWNLOAD_METHOD_POST;
|
||||
return in_array($site_name, $method) ? 'POST' : 'GET';
|
||||
$node = $item->getElementsByTagName('description')->item(0);
|
||||
if ($node != null) {
|
||||
$item->removeChild($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* 公共方法:实现rss订阅下载,子类可以重写此方法
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
echo "正在初始化RPC链接...". PHP_EOL;
|
||||
Rpc::init($this->site, static::getTorrentDownloadMethod($this->site), self::$conf);
|
||||
$html = $this->get();
|
||||
#cli($html);
|
||||
$this->checkCallback($html);
|
||||
$data = $this->decode($html);
|
||||
echo "已解码,正在推送给RPC下载器...". PHP_EOL;
|
||||
//cli($data);exit;
|
||||
Rpc::call($data);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求url,获取html页面,子类可以重写此方法
|
||||
* @return string
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
if (!empty(static::$conf['urladdress'])) {
|
||||
$url = static::$conf['urladdress'];
|
||||
} else {
|
||||
$url = $this->rss_page;
|
||||
}
|
||||
if (empty($url)) {
|
||||
die('缺少 rss.page 配置');
|
||||
}
|
||||
$url = str_replace("{}", $this->passkey, $url);
|
||||
echo $this->site." 正在请求RSS... {$url}". PHP_EOL;
|
||||
$url = (stripos($url, 'http://') === 0 || stripos($url, 'https://') === 0) ? $url : $this->host . $url;
|
||||
$res = $this->curl->get($url);
|
||||
//cli($res);exit;
|
||||
if ($res->http_status_code == 200) {
|
||||
echo "RSS获取信息,成功!". PHP_EOL;
|
||||
return $res->response;
|
||||
}
|
||||
echo "RSS获取信息失败,请重试!". PHP_EOL;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调函数,子类可以重写此方法
|
||||
* @param string $html
|
||||
*/
|
||||
public function checkCallback($html = '')
|
||||
{
|
||||
if (strpos((string)$html, 'invalid passkey') !== false) {
|
||||
die('passkey填写错误,请重新填写!');
|
||||
}
|
||||
if (is_null($html)) {
|
||||
exit(1);
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置
|
||||
* @param null $key 配置键值
|
||||
* @param null $default 默认
|
||||
* @return array|mixed|null
|
||||
*/
|
||||
public static function getConfig($key = null, $default = null)
|
||||
{
|
||||
if ($key === null) {
|
||||
return self::$conf;
|
||||
}
|
||||
$key_array = \explode('.', $key);
|
||||
$value = self::$conf;
|
||||
foreach ($key_array as $index) {
|
||||
if (!isset($value[$index])) {
|
||||
return $default;
|
||||
}
|
||||
$value = $value[$index];
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得当前站点HOST
|
||||
* @return string
|
||||
*/
|
||||
protected static function getHost():string
|
||||
{
|
||||
//站点配置
|
||||
$sites = static::$conf['sites'];
|
||||
$protocol = isset($sites['is_https']) && ($sites['is_https'] === 0) ? 'http://' : 'https://';
|
||||
$domain = $sites['base_url'];
|
||||
return $protocol . $domain . '/'; // 示例:https://baidu.com/
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得用户浏览器UA
|
||||
* @return string
|
||||
*/
|
||||
protected static function getUserAgent():string
|
||||
{
|
||||
//常规配置
|
||||
$default = empty(static::$conf['default']) ? [] : static::$conf['default'];
|
||||
return !empty($default['ua']) ? $default['ua'] : Constant::UserAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽象方法,在子类中实现
|
||||
* 解码html为种子数组
|
||||
* @param string $html
|
||||
* @return array
|
||||
* 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时<br />46分
|
||||
)
|
||||
[comments] => 0
|
||||
[size] => 5232.64MB
|
||||
[seeders] => 69
|
||||
[leechers] => 10
|
||||
[completed] => 93
|
||||
[percentage] => 100%
|
||||
[owner] => 匿名
|
||||
)
|
||||
*/
|
||||
abstract public function decode($html = '');
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* beitai RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class beitai extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* btschool RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class btschool extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* chdbits RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class chdbits extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* discfan RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class discfan extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* dmhy RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class dmhy extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* beitai RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class dragonhd extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* eastgame RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class eastgame extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* chdbits RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class haidan extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* hd4fans RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class hd4fans extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* hdai RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class hdai extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* hdarea RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class hdarea extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* hdatmos RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class hdatmos extends AbstractRss
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
use DOMDocument;
|
||||
|
@ -22,6 +23,7 @@ class hdbits extends AbstractRss
|
|||
* RSS订阅页面
|
||||
*/
|
||||
public $rss_page = 'rss/feed?passkey={}';
|
||||
|
||||
/**
|
||||
* 抽象方法,在类中实现
|
||||
* 请求url,获取html页面
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* hdchina RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class hdchina extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* hdcity RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
use Curl\Curl;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* hddolby RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class hddolby extends AbstractRss
|
||||
|
@ -24,6 +25,7 @@ class hddolby extends AbstractRss
|
|||
die($this->site . ' 没有配置密钥,初始化错误。' . PHP_EOL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽象方法,在类中实现
|
||||
* 解码html为种子数组
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* hdfans RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class hdfans extends AbstractRss
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
/**
|
||||
* hdhome RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class hdhome extends AbstractRss
|
||||
{
|
||||
public static $official = array('HDHome', 'HDH', 'HDHTV', 'HDHPad', 'HDHWEB');
|
||||
/**
|
||||
* 站点标志
|
||||
* @var string
|
||||
*/
|
||||
public $site = 'hdhome';
|
||||
|
||||
public static $official = array('HDHome','HDH','HDHTV','HDHPad','HDHWEB');
|
||||
|
||||
/**
|
||||
* 初始化 第二步
|
||||
*/
|
||||
|
@ -26,6 +26,7 @@ class hdhome extends AbstractRss
|
|||
die($this->site . ' 没有配置密钥,初始化错误。' . PHP_EOL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽象方法,在类中实现
|
||||
* 解码html为种子数组
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
use DOMDocument;
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
/**
|
||||
* hdsky RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class hdsky extends AbstractRss
|
||||
{
|
||||
public static $official = array('HDSky', 'HDS', 'HDSPad', 'LUTV', 'iHD', 'HDSCD', 'HDSTV', 'HDSWEB');
|
||||
/**
|
||||
* 站点标志
|
||||
* @var string
|
||||
*/
|
||||
public $site = 'hdsky';
|
||||
|
||||
public static $official = array('HDSky','HDS','HDSPad','LUTV','iHD','HDSCD','HDSTV','HDSWEB');
|
||||
|
||||
/**
|
||||
* 抽象方法,在类中实现
|
||||
* 解码html为种子数组
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* hdtime RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class hdtime extends AbstractRss
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
use DOMDocument;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* hdzone RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class hdzone extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* hitpt RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class hitpt extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* joyhd RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class joyhd extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* keepfrds RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class keepfrds extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* leaguehd RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class leaguehd extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* mteam RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class mteam extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* nanyangpt RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class nanyangpt extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* nicept RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class nicept extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* npupt RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class npupt extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* opencd RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class opencd extends AbstractRss
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* oshen RSS解码类
|
||||
*/
|
||||
|
||||
namespace IYUU\Rss;
|
||||
|
||||
class oshen extends AbstractRss
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user