update webman

This commit is contained in:
david 2022-10-03 11:03:11 +08:00
parent a0cd0704e6
commit fb8e6a0234
553 changed files with 45100 additions and 6651 deletions

11
app/Request.php Normal file
View File

@ -0,0 +1,11 @@
<?php
namespace app;
/**
* Class Request
* @package support
*/
class Request extends \support\Request
{
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\common;
/**
@ -11,15 +12,15 @@ class Config
*/
const extMap = [
'array' => '.php',
'json' => '.json',
'object'=> '.data',
'json' => '.json',
'object' => '.data',
];
/**
* 写入配置
* @param string $filename 文件名
* @param mixed $data 数据
* @param string $type 数据类型
* @param string $filename 文件名
* @param mixed $data 数据
* @param string $type 数据类型
* @param bool $absolutePath 绝对路径
* @return bool|int
*/
@ -49,7 +50,7 @@ class Config
$str = json_encode($data, JSON_UNESCAPED_UNICODE);
break;
case 'array':
$str = '<?php'.PHP_EOL.'return ' . var_export($data, true) . ';'.PHP_EOL;
$str = '<?php' . PHP_EOL . 'return ' . var_export($data, true) . ';' . PHP_EOL;
break;
default:
$str = $data;
@ -60,11 +61,23 @@ 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 文件名
* @param string $type 数据类型
* @param null $default 默认值
* @param string $filename 文件名
* @param string $type 数据类型
* @param null $default 默认值
* @param bool $absolutePath 绝对路径
* @return false|string|null|array
*/
@ -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;
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\common;
/**
@ -26,13 +27,13 @@ class Constant
*/
const API_BASE = 'https://api.iyuu.cn';
const API = [
'login' => '/App.Api.Bind',
'sites' => '/App.Api.Sites',
'infohash' => '/App.Api.Infohash',
'hash' => '/App.Api.Hash',
'notify' => '/App.Api.Notify',
'login' => '/App.Api.Bind',
'sites' => '/App.Api.Sites',
'infohash' => '/App.Api.Infohash',
'hash' => '/App.Api.Hash',
'notify' => '/App.Api.Notify',
'recommend' => '/App.Api.GetRecommendSites',
'getSign' => '/App.Api.GetSign',
'getSign' => '/App.Api.GetSign',
];
/**
@ -60,9 +61,9 @@ class Constant
* @var array
*/
const RS = [
'ret' => 200,
'data' => [],
'msg' => ''
'ret' => 200,
'data' => [],
'msg' => ''
];
/**
@ -70,9 +71,9 @@ class Constant
*/
const SITENAME_TO_FILENAME_MAP = [
'1ptba' => 'ptba',
'52pt' => 'site52pt',
'm-team'=> 'mteam',
'hd-torrents'=> 'hdtorrents',
'52pt' => 'site52pt',
'm-team' => 'mteam',
'hd-torrents' => 'hdtorrents',
];
/**

View File

@ -1,4 +1,5 @@
<?php
namespace app\common;
/**
@ -72,7 +73,7 @@ class ICheck
];
/**
* 解析检查运行环境
* 解析检查运行环境
* @param string $currentOs
*/
public static function analysis(string $currentOs)

View File

@ -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,24 +71,12 @@ 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
* @param array|object|string $data 数据
* @param bool $asJson 是否Json
* @param bool $reset 是否重置Curl(默认true)
* @param array|object|string $data 数据
* @param bool $asJson 是否Json
* @param bool $reset 是否重置Curl(默认true)
* @return ICurl
*/
public static function post(string $url, $data = array(), bool $asJson = false, bool $reset = true): ICurl
@ -100,8 +101,8 @@ class Curl
{
$opts = array(
'http' => array(
'method' => 'POST',
'header' => 'Content-type: ' . ($asJson ? static::CONTENT_TYPE_JSON : static::CONTENT_TYPE_DEFAULT),
'method' => 'POST',
'header' => 'Content-type: ' . ($asJson ? static::CONTENT_TYPE_JSON : static::CONTENT_TYPE_DEFAULT),
'content' => (is_array($data) || is_object($data)) ? ($asJson ? json_encode($data, JSON_UNESCAPED_UNICODE) : http_build_query($data)) : $data,
'timeout' => 5
),
@ -111,7 +112,7 @@ class Curl
'verify_peer_name' => false,
)
);
$context = stream_context_create($opts);
$context = stream_context_create($opts);
return file_get_contents($url, false, $context);
}
@ -128,6 +129,6 @@ class Curl
if (method_exists(self::$_instance, $method) && is_callable([self::$_instance, $method])) {
return self::$_instance->{$method}(... $arguments);
}
throw new BusinessException($method. '不存在或不可调用');
throw new BusinessException($method . '不存在或不可调用');
}
}

View File

@ -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,30 +31,10 @@ 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处理方法
*
* @param object $event 当前事件对象
* @param object $event 当前事件对象
* @return string
* The Event that was passed, now modified by listeners.
*/
@ -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;
}
}

View File

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

View File

@ -1,5 +1,6 @@
<?php
declare(strict_types=1);
namespace app\common\event;
/**

View File

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

View File

@ -1,5 +1,6 @@
<?php
declare(strict_types=1);
namespace app\common\event;
/**
@ -21,5 +22,5 @@ interface StoppableEventInterface
* True if the Event is complete and no further listeners should be called.
* False to continue calling listeners.
*/
public function isPropagationStopped() : bool;
public function isPropagationStopped(): bool;
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\common\exception;
use Exception;

View File

@ -1,4 +1,5 @@
<?php
namespace app\common\exception;
use Throwable;
@ -31,19 +32,19 @@ class Handler extends ExceptionHandler
* @param Throwable $exception
* @return Response
*/
public function render(Request $request, Throwable $exception) : Response
public function render(Request $request, Throwable $exception): Response
{
$header = [
'Content-Type' => 'application/json; charset=utf-8',
'Connection' => 'close',
'Pragma' => 'no-cache'
'Content-Type' => 'application/json; charset=utf-8',
'Connection' => 'close',
'Pragma' => 'no-cache'
];
$code = $exception->getCode();
$error = $exception->getMessage();
$rs = [
'ret' => $code,
'data' => [],
'msg' => $error
'ret' => $code,
'data' => [],
'msg' => $error
];
if ($this->_debug) {

View File

@ -1,4 +1,5 @@
<?php
namespace app\controller;
use support\Request;
@ -49,7 +50,7 @@ class Api extends BaseController
{
$rs = self::RS;
$rs['data'] = [
'is_login' => domainUsers::isLogin($request)
'is_login' => domainUsers::isLogin($request)
];
return json($rs);
@ -161,8 +162,8 @@ class Api extends BaseController
public function Clear(Request $request): Response
{
$config = config('server');
Config::set($config['log_file'], date('Y-m-d H:i:s').' 清理日志'.PHP_EOL, 'raw', true);
Config::set($config['stdout_file'], date('Y-m-d H:i:s').' 清理日志'.PHP_EOL, 'raw', true);
Config::set($config['log_file'], date('Y-m-d H:i:s') . ' 清理日志' . PHP_EOL, 'raw', true);
Config::set($config['stdout_file'], date('Y-m-d H:i:s') . ' 清理日志' . PHP_EOL, 'raw', true);
return json(['code' => 1, 'msg' => '清理成功', 'data' => []]);
}

View File

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

View File

@ -1,4 +1,5 @@
<?php
namespace app\controller;
use app\domain\Users as domainUsers;
@ -38,7 +39,7 @@ class Index
{
$file = $request->file('upload');
if ($file && $file->isValid()) {
$file->move(public_path().'/files/myfile.'.$file->getUploadExtension());
$file->move(public_path() . '/files/myfile.' . $file->getUploadExtension());
return json(['code' => 0, 'msg' => 'upload success']);
}
return json(['code' => 1, 'msg' => 'file not found']);

View File

@ -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;
@ -27,8 +26,8 @@ class Status extends BaseController
$log_file = Conf::get($config['log_file'], 'raw', '', true);
$stdout_file = Conf::get($config['stdout_file'], 'raw', '', true);
$rs['data'] = [
'log_file' => $log_file,
'stdout_file' => $stdout_file,
'log_file' => $log_file,
'stdout_file' => $stdout_file,
];
return json($rs);
}
@ -66,28 +65,28 @@ class Status extends BaseController
$user_sites = Config::getUserSites();
$sites = Config::getSites();
$clients = Config::getClients();
$version = 'v'.IYUU_VERSION();
$version = 'v' . IYUU_VERSION();
$system_info = sprintf('%s / %s', PHP_OS, PHP_OS_FAMILY);
//读取git信息
$updated_at = get_current_git_filemtime() . (get_current_git_commit() ? ' (' . get_current_git_commit() . ')' : '');
$updated_at = get_current_git_filemtime() . (get_current_git_commit() ? ' (' . get_current_git_commit() . ')' : '');
$updated_at = strlen($updated_at) > 10 ? $updated_at : '点此查看';
// 磁盘容量、可用容量
$disk_total_space = disk_total_space(db_path());
$disk_free_space = disk_free_space(db_path());
$disk_free_space = disk_free_space(db_path());
$disk_total = \sprintf('可用:%s总容量%s', \dataSize($disk_free_space), \dataSize($disk_total_space));
$rs['data'] = [
'cron_total' => count($cron),
'sites_total' => count($user_sites),
'sites_conut' => count($sites),
'cron_total' => count($cron),
'sites_total' => count($user_sites),
'sites_conut' => count($sites),
'clients_total' => count($clients),
'project' => IYUU_PROJECT_NAME(),
'version' => $version,
'updated_at' => $updated_at,
'system_info' => $system_info,
'PHP_VERSION' => PHP_VERSION,
'PHP_BINARY' => PHP_BINARY,
'RUNTIME_PATH' => runtime_path(),
'disk_total' => $disk_total,
'project' => IYUU_PROJECT_NAME(),
'version' => $version,
'updated_at' => $updated_at,
'system_info' => $system_info,
'PHP_VERSION' => PHP_VERSION,
'PHP_BINARY' => PHP_BINARY,
'RUNTIME_PATH' => runtime_path(),
'disk_total' => $disk_total,
];
return json($rs);
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\controller;
use support\Request;

View File

@ -1,4 +1,5 @@
<?php
namespace app\domain;
/**
@ -12,10 +13,10 @@ class Command
* @param array $param
* @return string
*/
public static function parse(array $param):string
public static function parse(array $param): string
{
$taskType = $param['type'] ?? 'default';
$className = "app\\domain\\Command\\".$taskType;
$className = "app\\domain\\Command\\" . $taskType;
if (\class_exists($className)) {
$obj = new $className;
if ($obj instanceof CommandInterface) {
@ -23,6 +24,6 @@ class Command
}
}
return '计划任务命令解析类 '. $className .' 不存在';
return '计划任务命令解析类 ' . $className . ' 不存在';
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\domain\Command;
use app\domain\CommandInterface;
@ -12,6 +13,6 @@ class move implements CommandInterface
{
public function parse(array $param): string
{
return PHP_BINARY . ' ' . BASE_PATH . DIRECTORY_SEPARATOR . 'bin/move.php '.$param['uuid'];
return PHP_BINARY . ' ' . BASE_PATH . DIRECTORY_SEPARATOR . 'bin/move.php ' . $param['uuid'];
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\domain\Command;
use app\domain\CommandInterface;
@ -12,6 +13,6 @@ class reseed implements CommandInterface
{
public function parse(array $param): string
{
return PHP_BINARY . ' ' . BASE_PATH . DIRECTORY_SEPARATOR . 'bin/iyuu.php '.$param['uuid'];
return PHP_BINARY . ' ' . BASE_PATH . DIRECTORY_SEPARATOR . 'bin/iyuu.php ' . $param['uuid'];
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\domain\Command;
use app\domain\CommandInterface;
@ -12,6 +13,6 @@ class rss implements CommandInterface
{
public function parse(array $param): string
{
return PHP_BINARY . ' ' . BASE_PATH . DIRECTORY_SEPARATOR . 'bin/rss.php '.$param['uuid'];
return PHP_BINARY . ' ' . BASE_PATH . DIRECTORY_SEPARATOR . 'bin/rss.php ' . $param['uuid'];
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\domain\Command;
use app\domain\CommandInterface;
@ -12,6 +13,6 @@ class spiders implements CommandInterface
{
public function parse(array $param): string
{
return PHP_BINARY . ' ' . BASE_PATH . DIRECTORY_SEPARATOR . 'bin/spiders.php '.$param['uuid'];
return PHP_BINARY . ' ' . BASE_PATH . DIRECTORY_SEPARATOR . 'bin/spiders.php ' . $param['uuid'];
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\domain;
/**
@ -8,5 +9,5 @@ namespace app\domain;
*/
interface CommandInterface
{
public function parse(array $param):string;
public function parse(array $param): string;
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\domain;
use app\common\Config as Conf;
@ -18,26 +19,26 @@ class Config
'clients' => 'clients',
'crontab' => 'crontab',
'default' => 'default',
'filter' => 'filter',
'folder' => 'folder',
'init' => 'init',
'iyuu' => 'iyuu',
'mail' => 'mail',
'sites' => 'sites',
'sms' => 'sms',
'user' => 'user',
'user_sites'=> 'user_sites',
'weixin' => 'weixin',
'filter' => 'filter',
'folder' => 'folder',
'init' => 'init',
'iyuu' => 'iyuu',
'mail' => 'mail',
'sites' => 'sites',
'sms' => 'sms',
'user' => 'user',
'user_sites' => 'user_sites',
'weixin' => 'weixin',
'userProfile' => 'userProfile',
];
/**
* 主入口
* @param string $config_filename 配置文件名
* @param Request $request 请求对象
* @param string $config_filename 配置文件名
* @param Request $request 请求对象
* @return array
*/
public static function main(string $config_filename, Request $request):array
public static function main(string $config_filename, Request $request): array
{
$rs = Constant::RS;
// 取值优先级get > post
@ -63,12 +64,12 @@ class Config
/**
* 用UUID模拟数据库主键实现配置的增删改查
* @param string $config_filename 配置文件名
* @param Request $request 请求对象
* @param null $PRIMARY 主键
* @param string $config_filename 配置文件名
* @param Request $request 请求对象
* @param null $PRIMARY 主键
* @return array
*/
public static function uuid(string $config_filename, Request $request, $PRIMARY = null):array
public static function uuid(string $config_filename, Request $request, $PRIMARY = null): array
{
$rs = Constant::RS;
$old_config = Conf::get($config_filename, Constant::config_format, []);
@ -127,20 +128,6 @@ class Config
return $rs;
}
/**
* 简单操作的增删改查
* @param string $config_filename
* @param Request $request
* @return array
*/
public static function default(string $config_filename, Request $request):array
{
$data = $request->post();
self::createDataExcludeKeys($data);
Conf::set($config_filename, $data, Constant::config_format);
return Constant::RS;
}
/**
* 排除字段
* @param $data
@ -154,11 +141,25 @@ class Config
}
}
/**
* 简单操作的增删改查
* @param string $config_filename
* @param Request $request
* @return array
*/
public static function default(string $config_filename, Request $request): array
{
$data = $request->post();
self::createDataExcludeKeys($data);
Conf::set($config_filename, $data, Constant::config_format);
return Constant::RS;
}
/**
* IYUU密钥
* @return array
*/
public static function getIyuu():array
public static function getIyuu(): array
{
return Conf::get(self::filename['iyuu'], Constant::config_format, []);
}
@ -167,7 +168,7 @@ class Config
* 默认配置
* @return array
*/
public static function getDefault():array
public static function getDefault(): array
{
return Conf::get(self::filename['default'], Constant::config_format, []);
}
@ -176,43 +177,25 @@ class Config
* 客户端
* @return array
*/
public static function getClients():array
public static function getClients(): array
{
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
*/
public static function getFolder():array
public static function getFolder(): array
{
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
*/
public static function getSites():array
public static function getSites(): array
{
return Conf::get(self::filename['sites'], Constant::config_format, []);
}
@ -221,7 +204,7 @@ class Config
* 过滤器
* @return array
*/
public static function getFilter():array
public static function getFilter(): array
{
return Conf::get(self::filename['filter'], Constant::config_format, []);
}
@ -230,7 +213,7 @@ class Config
* 微信配置
* @return array
*/
public static function getWeixin():array
public static function getWeixin(): array
{
return Conf::get(self::filename['weixin'], Constant::config_format, []);
}
@ -240,18 +223,27 @@ class Config
* @param string $uuid
* @return array
*/
public static function getCronByUUID(string $uuid = ''):array
public static function getCronByUUID(string $uuid = ''): array
{
$cron = self::getCrontab();
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
* @return array
*/
public static function disabledUserSites(array &$sites):array
public static function disabledUserSites(array &$sites): array
{
$user_sites = self::getUserSites();
array_walk($sites, function (&$v, $k) use ($user_sites) {
@ -262,12 +254,21 @@ class Config
return $sites;
}
/**
* 用户拥有的站点
* @return array
*/
public static function getUserSites(): array
{
return Conf::get(self::filename['user_sites'], Constant::config_format, []);
}
/**
* 禁用用户未配置的站点
* @param array $sites
* @return array
*/
public static function disabledNotConfiguredUserSites(array &$sites):array
public static function disabledNotConfiguredUserSites(array &$sites): array
{
$user_sites = self::getUserSites();
array_walk($sites, function (&$v, $k) use ($user_sites) {

View File

@ -1,4 +1,5 @@
<?php
namespace app\domain\ConfigParser;
use app\domain\ConfigParserInterface;
@ -10,24 +11,25 @@ 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' => [],
'form_clients' => [],
'to_clients' => [],
'path_filter' => [],
'clients' => [],
'form_clients' => [],
'to_clients' => [],
'path_filter' => [],
'path_selector' => [],
'path_type' => 0,
'path_rule' => [],
'skip_check' => 0,
'paused' => 1,
'delete_torrent'=> 0,
'path_type' => 0,
'path_rule' => [],
'skip_check' => 0,
'paused' => 1,
'delete_torrent' => 0,
];
if (empty($uuid)) {
return $rs;
@ -102,10 +104,10 @@ class Move implements ConfigParserInterface
/**
* 从目录配置中挑选需要的数据
* @param string $key 配置的键
* @param array $cron 定时任务配置
* @param array $folder 目录配置
* @param array $rs 返回的转移做种配置
* @param string $key 配置的键
* @param array $cron 定时任务配置
* @param array $folder 目录配置
* @param array $rs 返回的转移做种配置
*/
private static function getDir($key, $cron, $folder, &$rs)
{
@ -131,7 +133,7 @@ class Move implements ConfigParserInterface
* @param string $str
* @return string
*/
private static function replaceBr(string $str = ''):string
private static function replaceBr(string $str = ''): string
{
while (strpos($str, "\r\n") !== false) {
$str = str_replace("\r\n", "\n", $str);
@ -144,7 +146,7 @@ class Move implements ConfigParserInterface
* @param array $path_rule
* @return array
*/
private static function getPathRule(array $path_rule = []):array
private static function getPathRule(array $path_rule = []): array
{
$rule = [];
if (count($path_rule)) {

View File

@ -1,4 +1,5 @@
<?php
namespace app\domain\ConfigParser;
use app\domain\ConfigParserInterface;
@ -18,10 +19,10 @@ class Reseed implements ConfigParserInterface
* @param string $uuid
* @return array
*/
public static function parser($uuid = ''):array
public static function parser(string $uuid = ''): array
{
$rs = [
'sites' => [],
'sites' => [],
'clients' => [],
];
if (empty($uuid)) {
@ -65,41 +66,41 @@ class Reseed implements ConfigParserInterface
return $rs;
}
/**
* 获取辅种缓存的存放路径
* @return string
*/
public static function getReseedCachePath():string
{
return runtime_path() . DIRECTORY_SEPARATOR . 'torrent' . DIRECTORY_SEPARATOR . 'cachehash';
}
/**
* 获取转移缓存的存放路径
* @return string
*/
public static function getMoveCachePath():string
{
return runtime_path() . DIRECTORY_SEPARATOR . 'torrent' . DIRECTORY_SEPARATOR . 'cachemove';
}
/**
* 清理辅种缓存
* @return bool
*/
public static function clearReseedCache():bool
public static function clearReseedCache(): bool
{
$dir = self::getReseedCachePath();
return is_dir($dir) ? IFile::rmdir($dir, true) : true;
return !is_dir($dir) || IFile::rmdir($dir, true);
}
/**
* 获取辅种缓存的存放路径
* @return string
*/
public static function getReseedCachePath(): string
{
return runtime_path() . DIRECTORY_SEPARATOR . 'torrent' . DIRECTORY_SEPARATOR . 'cachehash';
}
/**
* 清理转移缓存
* @return bool
*/
public static function clearMoveCache():bool
public static function clearMoveCache(): bool
{
$dir = self::getMoveCachePath();
return is_dir($dir) ? IFile::rmdir($dir, true) : true;
return !is_dir($dir) || IFile::rmdir($dir, true);
}
/**
* 获取转移缓存的存放路径
* @return string
*/
public static function getMoveCachePath(): string
{
return runtime_path() . DIRECTORY_SEPARATOR . 'torrent' . DIRECTORY_SEPARATOR . 'cachemove';
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\domain\ConfigParser;
use app\domain\ConfigParserInterface;
@ -11,13 +12,13 @@ class Rss implements ConfigParserInterface
* @param string $uuid
* @return array
*/
public static function parser($uuid = ''):array
public static function parser(string $uuid = ''): array
{
$rs = [
'site' => [],
'sites' => [],
'site' => [],
'sites' => [],
'clients' => [],
'filter' => [],
'filter' => [],
];
if (empty($uuid)) {
return $rs;
@ -75,7 +76,7 @@ class Rss implements ConfigParserInterface
* @descr 步骤1.获取Rss目录下的全部类文件名 2.实例化类为对象; 3.获取对象的成员变量site
* @return array
*/
public static function getAllRssClass():array
public static function getAllRssClass(): array
{
$data = [];
//排除的类
@ -86,7 +87,7 @@ class Rss implements ConfigParserInterface
if (in_array($filename, $filter)) {
continue;
}
$classname = "IYUU\\Rss\\".$filename;
$classname = "IYUU\\Rss\\" . $filename;
if (class_exists($classname)) {
$obj = new $classname(false);
$data[] = $obj->site;
@ -102,7 +103,7 @@ class Rss implements ConfigParserInterface
* @param array $data
* @return array
*/
public static function formatSites(array $data = []):array
public static function formatSites(array $data = []): array
{
$sites = Config::getSites();
$sites = array_filter($sites, function ($k) use ($data) {

View File

@ -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);
}
@ -21,7 +22,7 @@ class Spiders implements ConfigParserInterface
* @descr 步骤1.获取Rss目录下的全部类文件名 2.实例化类为对象; 3.获取对象的成员变量site
* @return array
*/
public static function getAllSpidersClass():array
public static function getAllSpidersClass(): array
{
$data = [];
//排除的类
@ -32,7 +33,7 @@ class Spiders implements ConfigParserInterface
if (in_array($filename, $filter)) {
continue;
}
$classname = "IYUU\\Spiders\\".$filename;
$classname = "IYUU\\Spiders\\" . $filename;
if (class_exists($classname)) {
$data[] = SitesBase::getSiteName($filename);
}
@ -47,7 +48,7 @@ class Spiders implements ConfigParserInterface
* @param array $data
* @return array
*/
public static function formatSites(array $data = []):array
public static function formatSites(array $data = []): array
{
return Rss::formatSites($data);
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\domain;
/**
@ -8,5 +9,5 @@ namespace app\domain;
*/
interface ConfigParserInterface
{
public static function parser(string $uuid):array;
public static function parser(string $uuid): array;
}

View File

@ -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'
'day', 'day_n', 'hour', 'hour_n', 'minute', 'minute_n', 'second', 'second_n', 'week', 'month'
];
public static $adminName = '';
public static $adminPassword = '';
/**
* 构造方法
@ -97,27 +96,9 @@ 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 数据
* @param array $param 数据
* array(
* 'where' => ''
* 'weeks' => ''
@ -137,15 +118,15 @@ class Crontab
* | +----------- min (0 - 59)
* +------------- sec (0-59)
*/
public static function parseCron(array $param):string
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');
}
@ -157,25 +138,25 @@ class Crontab
$cron = sprintf(self::cron_minute, $minute, $hour, '*', '*', '*');
break;
case 'day_n': //N天
$cron = sprintf(self::cron_minute, $minute, $hour, '*/'.$day, '*', '*');
$cron = sprintf(self::cron_minute, $minute, $hour, '*/' . $day, '*', '*');
break;
case 'hour': //每小时
$cron = sprintf(self::cron_minute, $minute, '*', '*', '*', '*');
break;
case 'hour_n': //N小时
$cron = sprintf(self::cron_minute, $minute, '*/'.$hour, '*', '*', '*');
$cron = sprintf(self::cron_minute, $minute, '*/' . $hour, '*', '*', '*');
break;
case 'minute': //每分钟
$cron = sprintf(self::cron_minute, '*', '*', '*', '*', '*');
break;
case 'minute_n': //N分钟
$cron = sprintf(self::cron_minute, '*/'.$minute, '*', '*', '*', '*');
$cron = sprintf(self::cron_minute, '*/' . $minute, '*', '*', '*', '*');
break;
case 'second': //每秒
$cron = sprintf(self::cron_second, '*', '*', '*', '*', '*', '*');
break;
case 'second_n': //N秒
$cron = sprintf(self::cron_second, '*/'.$second, '*', '*', '*', '*', '*');
$cron = sprintf(self::cron_second, '*/' . $second, '*', '*', '*', '*', '*');
break;
case 'week': //每周
$cron = sprintf(self::cron_minute, $minute, $hour, '*', '*', $weeks);
@ -193,36 +174,54 @@ class Crontab
* @param array $param
* @return string
*/
public static function parseCommand(array $param):string
public static function parseCommand(array $param): string
{
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 文件名
* @param string $dir 子目录
* @param string $suffix 扩展名
* @param string $filename 文件名
* @param string $dir 子目录
* @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;
is_dir($_dir) or mkdir($_dir, 0777, true);
return $_dir . DIRECTORY_SEPARATOR . $filename . $suffix;
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;
}
/**
@ -230,7 +229,7 @@ class Crontab
* @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,27 +239,17 @@ 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
* @return bool
*/
public static function runCron(string $uuid = ''):bool
public static function runCron(string $uuid = ''): bool
{
$cronFilename = Config::filename['crontab'];
$cronAll = Conf::get($cronFilename, Constant::config_format, []);
@ -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');
}
/**
@ -288,18 +296,29 @@ class Crontab
* @param string $uuid
* @return bool
*/
public static function clearLogs(string $uuid = ''):bool
public static function clearLogs(string $uuid = ''): bool
{
$logFile = self::getLogFile($uuid);
$ret = Conf::set($logFile, date('Y-m-d H:i:s').' 清理日志'.PHP_EOL, 'raw', true);
$ret = Conf::set($logFile, date('Y-m-d H:i:s') . ' 清理日志' . PHP_EOL, 'raw', true);
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
*/
public static function clearAllLogs():int
public static function clearAllLogs(): int
{
$cron = Config::getCrontab();
$count = 0;
@ -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 &');
}
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\domain;
use support\Request;
@ -18,57 +19,12 @@ class Users
* @param Request $request
* @return bool
*/
public static function isLogin(Request $request):bool
public static function isLogin(Request $request): bool
{
$session = $request->session();
return $session->has(Constant::Session_Token_Key);
}
/**
* 检查token及绑定状态
* - 接口api.iyuu.cn返回的信息原样返回给前端
* @descr 接口地址 https://api.iyuu.cn/index.php?s=App.Api.Sites
* 接口文档 https://api.iyuu.cn/docs.php?service=App.Api.Sites&detail=1&type=fold
* @param string $token
* @param Request $request
* @return array
*/
public static function checkToken(string $token, Request $request):array
{
$curl = Curl::one();
$api_url = Constant::API_BASE;
$api_action = Constant::API['sites'];
$url = sprintf('%s%s?sign=%s&version=%s', $api_url, $api_action, $token, IYUU_VERSION());
$res = $curl->get($url);
$rs = json_decode($res->response, true);
if (empty($res->response) || empty($rs) || !is_array($rs)) {
$rs = Constant::RS;
$rs['ret'] = 500;
$rs['msg'] = "无法访问{$api_url}接口请检查本地网络或重新创建容器改为HOST网络模式。";
return $rs;
}
file_put_contents(db_path().'/_response.json', print_r($res->response, true));
if (isset($rs['ret']) && ($rs['ret'] === 200) && isset($rs['data']['sites']) && is_array($rs['data']['sites'])) {
$sites = array_column($rs['data']['sites'], null, 'site');
Conf::set('sites', $sites, Constant::config_format);
Conf::set('iyuu', ['iyuu.cn' => $token], Constant::config_format);
// 验证通过写入Session
$session = $request->session();
$session->set(Constant::Session_Token_Key, $token);
} else {
/**
* 接口api.iyuu.cn在用户的token未激活时会返回403状态码 推荐站点列表,供用户填写绑定信息
*/
if (isset($rs['ret']) && ($rs['ret'] === 403) && isset($rs['data']['recommend']) && is_array($rs['data']['recommend'])) {
//用户未绑定合作站点
$recommend = $rs['data']['recommend'];
Conf::set('recommend', $recommend, Constant::config_format);
Conf::set('iyuu', ['iyuu.cn' => $token], Constant::config_format);
}
}
return $rs;
}
/**
* 用户绑定
* @descr 接口地址 https://api.iyuu.cn/index.php?s=App.User.Login
@ -77,15 +33,15 @@ class Users
* @param Request $request
* @return array
*/
public static function bindToken(string $token, Request $request):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'),
'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);
@ -108,13 +64,58 @@ class Users
}
}
/**
* 检查token及绑定状态
* - 接口api.iyuu.cn返回的信息原样返回给前端
* @descr 接口地址 https://api.iyuu.cn/index.php?s=App.Api.Sites
* 接口文档 https://api.iyuu.cn/docs.php?service=App.Api.Sites&detail=1&type=fold
* @param string $token
* @param Request $request
* @return array
*/
public static function checkToken(string $token, Request $request): array
{
$curl = Curl::one();
$api_url = Constant::API_BASE;
$api_action = Constant::API['sites'];
$url = sprintf('%s%s?sign=%s&version=%s', $api_url, $api_action, $token, IYUU_VERSION());
$res = $curl->get($url);
$rs = json_decode($res->response, true);
if (empty($res->response) || empty($rs) || !is_array($rs)) {
$rs = Constant::RS;
$rs['ret'] = 500;
$rs['msg'] = "无法访问{$api_url}接口请检查本地网络或重新创建容器改为HOST网络模式。";
return $rs;
}
file_put_contents(db_path() . '/_response.json', print_r($res->response, true));
if (isset($rs['ret']) && ($rs['ret'] === 200) && isset($rs['data']['sites']) && is_array($rs['data']['sites'])) {
$sites = array_column($rs['data']['sites'], null, 'site');
Conf::set('sites', $sites, Constant::config_format);
Conf::set('iyuu', ['iyuu.cn' => $token], Constant::config_format);
// 验证通过写入Session
$session = $request->session();
$session->set(Constant::Session_Token_Key, $token);
} else {
/**
* 接口api.iyuu.cn在用户的token未激活时会返回403状态码 推荐站点列表,供用户填写绑定信息
*/
if (isset($rs['ret']) && ($rs['ret'] === 403) && isset($rs['data']['recommend']) && is_array($rs['data']['recommend'])) {
//用户未绑定合作站点
$recommend = $rs['data']['recommend'];
Conf::set('recommend', $recommend, Constant::config_format);
Conf::set('iyuu', ['iyuu.cn' => $token], Constant::config_format);
}
}
return $rs;
}
/**
* 验证用户输入的密码
* @param Request $request
* @return bool
* @throws BusinessException
*/
public static function checkPassword(Request $request):bool
public static function checkPassword(Request $request): bool
{
$password = $request->get('password');
if (empty($password)) {
@ -134,27 +135,36 @@ class Users
return true;
}
/**
* 用户特征文件名
* @return string
*/
public static function getUserProfileName(): string
{
return 'userProfile';
}
/**
* 设置用户密码
* @param string $password
* @return bool
* @throws BusinessException
*/
public static function setPassword(string $password):bool
public static function setPassword(string $password): bool
{
//粗略验证
if (strlen($password) < 6) {
throw new BusinessException('密码必须超过6位', 250);
}
if (in_array($password, ['admin','root','adminadmin','administrator'])) {
if (in_array($password, ['admin', 'root', 'adminadmin', 'administrator'])) {
throw new BusinessException('密码太弱,不安全', 250);
}
$salt = getUUID(); //太淡了,加点盐
$userProfile = [
'pass_hash' => self::createPassHash($password, $salt),
'salt' => $salt,
'created_at' => time()
'salt' => $salt,
'created_at' => time()
];
return Conf::set(self::getUserProfileName(), $userProfile, 'json');
@ -166,17 +176,8 @@ class Users
* @param string $salt
* @return string
*/
public static function createPassHash(string $password, string $salt):string
public static function createPassHash(string $password, string $salt): string
{
return md5($salt . $password . $salt);
}
/**
* 用户特征文件名
* @return string
*/
public static function getUserProfileName():string
{
return 'userProfile';
}
}

View File

@ -1,4 +1,9 @@
<?php
/**
* 自定义函数
* 【载入时机】worker子进程
*/
use app\common\components\Curl as ICurl;
use app\domain\Config as domainConfig;
@ -6,7 +11,7 @@ use app\domain\Config as domainConfig;
* 返回IYUU客户端版本号
* @return string
*/
function IYUU_VERSION():string
function IYUU_VERSION(): string
{
return '2.0.7';
}
@ -15,7 +20,7 @@ function IYUU_VERSION():string
* 返回项目名称
* @return string
*/
function IYUU_PROJECT_NAME():string
function IYUU_PROJECT_NAME(): string
{
return 'IYUUPlus';
}
@ -26,7 +31,7 @@ function IYUU_PROJECT_NAME():string
* @param bool $short
* @return string
*/
function get_current_git_commit(string $branch = 'master', bool $short = true):string
function get_current_git_commit(string $branch = 'master', bool $short = true): string
{
if ($hash = file_get_contents(sprintf(base_path() . '/.git/refs/heads/%s', $branch))) {
$hash = trim($hash);
@ -41,7 +46,7 @@ function get_current_git_commit(string $branch = 'master', bool $short = true):s
* @param string $branch
* @return string
*/
function get_current_git_filemtime(string $branch = 'master'):string
function get_current_git_filemtime(string $branch = 'master'): string
{
if ($time = filemtime(sprintf(base_path() . '/.git/refs/heads/%s', $branch))) {
return date("Y-m-d H:i:s", $time);
@ -68,7 +73,7 @@ function ff(string $text = '', string $desp = '')
'text' => $text,
'desp' => $desp
);
return ICurl::http_post('https://iyuu.cn/'.$token.'.send', $data);
return ICurl::http_post('https://iyuu.cn/' . $token . '.send', $data);
}
/**
@ -76,7 +81,7 @@ function ff(string $text = '', string $desp = '')
* @param int $pid
* @return string
*/
function getUUID(int $pid = 0):string
function getUUID(int $pid = 0): string
{
if (function_exists('posix_getpid')) {
$pid = posix_getpid();
@ -89,7 +94,7 @@ function getUUID(int $pid = 0):string
* @param string $token
* @return bool
*/
function check_token(string $token = ''):bool
function check_token(string $token = ''): bool
{
return (strlen($token) < 60) && (strpos($token, 'IYUU') === 0) && (strpos($token, 'T') < 15);
}
@ -102,7 +107,7 @@ function check_token(string $token = ''):bool
function run_exec(string $cmd = '')
{
if (DIRECTORY_SEPARATOR === '\\') {
pclose(popen('start /B '.$cmd, 'r'));
pclose(popen('start /B ' . $cmd, 'r'));
} else {
pclose(popen($cmd, 'r'));
}
@ -110,12 +115,12 @@ function run_exec(string $cmd = '')
/**
* 转换成易读的容量格式(包含小数)
* @param int|float $bytes 字节
* @param string $delimiter 分隔符 [&nbsp; | <br />]
* @param int $decimals 保留小数点
* @param int|float $bytes 字节
* @param string $delimiter 分隔符 [&nbsp; | <br />]
* @param int $decimals 保留小数点
* @return string
*/
function dataSize($bytes, string $delimiter = '', int $decimals = 2):string
function dataSize($bytes, string $delimiter = '', int $decimals = 2): string
{
$type = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
$i = 0;
@ -129,8 +134,8 @@ function dataSize($bytes, string $delimiter = '', int $decimals = 2):string
/**
* 工具函数,读取文件最后$n行
* @param string $filename 文件的路径
* @param int $n 文件的行数
* @param string $filename 文件的路径
* @param int $n 文件的行数
* @return string
*/
function fileLastLines(string $filename, int $n = 1): ?string

114
app/helpers.php Normal file
View 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;
}

View File

@ -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;
@ -20,7 +20,7 @@ use Webman\Http\Request;
class AccessControlTest implements MiddlewareInterface
{
public function process(Request $request, callable $next) : Response
public function process(Request $request, callable $next): Response
{
// 允许uri以 /api 开头的地址跨域访问
if (strpos($request->path(), '/api') === 0) {

View File

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

View File

@ -1,4 +1,5 @@
<?php
namespace app\middleware;
use Webman\MiddlewareInterface;
@ -12,7 +13,7 @@ use app\common\Constant;
*/
class AuthCheck implements MiddlewareInterface
{
public function process(Request $request, callable $next) : Response
public function process(Request $request, callable $next): Response
{
$session = $request->session();
$action = $request->action;

View File

@ -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;
@ -20,7 +20,7 @@ use Webman\Http\Request;
class StaticFile implements MiddlewareInterface
{
public function process(Request $request, callable $next) : Response
public function process(Request $request, callable $next): Response
{
// 禁止访问.开头的隐藏文件
if (strpos($request->path(), '/.') !== false) {

View File

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

View File

@ -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>

View File

@ -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;
echo microtime(true) . ' 当前脚本路径:' . __FILE__ . PHP_EOL;
use IYUU\Reseed\AutoReseed;
use Workerman\Autoloader;

View File

@ -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;
echo microtime(true) . ' 当前脚本路径:' . __FILE__ . PHP_EOL;
use IYUU\Reseed\MoveTorrent;
use Workerman\Autoloader;

View File

@ -1,8 +1,8 @@
<?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;
echo microtime(true) . ' 当前脚本路径:' . __FILE__ . PHP_EOL;
use IYUU\Rss\AbstractRss;
use Workerman\Autoloader;
@ -11,16 +11,16 @@ Autoloader::setRootPath(ROOT_PATH);
global $argv;
echo "RSS订阅脚本目前支持以下站点".PHP_EOL;
echo "RSS订阅脚本目前支持以下站点" . PHP_EOL;
ShowTableSites('Rss');
if (count($argv) < 2) {
echo "执行RSS订阅命令时缺少参数".PHP_EOL;
echo "执行RSS订阅命令时缺少参数" . PHP_EOL;
exit(1);
}
// php脚本文件
$start_file = $argv[0];
// 参数1任务标志
$uuid = trim($argv[1]);
$uuid = trim($argv[1]);
// 通用部分
$obj = AbstractRss::getInstance($uuid);

View File

@ -1,8 +1,8 @@
<?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;
echo microtime(true) . ' 当前脚本路径:' . __FILE__ . PHP_EOL;
use IYUU\Spiders\SitesBase;
use Workerman\Autoloader;
@ -10,16 +10,16 @@ use Workerman\Autoloader;
Autoloader::setRootPath(ROOT_PATH);
global $argv;
echo "免费种爬虫,目前支持以下站点:".PHP_EOL;
echo "免费种爬虫,目前支持以下站点:" . PHP_EOL;
ShowTableSites('Spiders');
if (count($argv) < 2) {
echo "执行免费种爬虫命令时,缺少参数!!".PHP_EOL;
echo "执行免费种爬虫命令时,缺少参数!!" . PHP_EOL;
exit(1);
}
// php脚本文件
$start_file = $argv[0];
// 参数1任务标志
$uuid = trim($argv[1]);
$uuid = trim($argv[1]);
// 通用部分
$className = SitesBase::getSpidersClass($uuid);

View File

@ -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"
]
}
}

View File

@ -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,
];

View File

@ -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',
]
];

View File

@ -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,
];

View File

@ -1,6 +1,2 @@
<?php
return [
'EventListener' => [
IYUU\Library\EventListen\send::class,
],
];
return [];

View File

@ -19,11 +19,12 @@ return [
'class' => Monolog\Handler\RotatingFileHandler::class,
'constructor' => [
runtime_path() . '/logs/webman.log',
7, //$maxFiles
Monolog\Logger::DEBUG,
],
'formatter' => [
'class' => Monolog\Formatter\LineFormatter::class,
'constructor' => [ null, 'Y-m-d H:i:s', true],
'constructor' => [null, 'Y-m-d H:i:s', true],
],
]
],

View File

@ -5,8 +5,6 @@
return [
'' => [
app\middleware\AuthCheck::class,
app\middleware\ActionHook::class,
//support\middleware\AuthCheckTest::class,
//support\middleware\AccessControlTest::class,
]
];

View File

@ -19,9 +19,9 @@ use support\view\ThinkPHP;
return [
// 文件更新检测
'IYUUFileMonitor' => [
'handler' => process\FileMonitor::class,
'reloadable' => false,
'monitor' => [
'handler' => process\Monitor::class,
'reloadable' => false,
'constructor' => [
// 监控这些目录
'monitor_dir' => [
@ -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'
]
]
],
// 其它进程
@ -44,7 +45,7 @@ return [
'listen' => 'websocket://0.0.0.0:8888',
'count' => 1,
],*/
'IYUUTask' => [
'handler' => process\Task::class
'IYUUTask' => [
'handler' => process\Task::class
],
];

View File

@ -1,15 +1,18 @@
<?php
return [
'listen' => 'http://0.0.0.0:8787',
'transport' => 'tcp',
'context' => [],
'name' => 'IYUUAutoReseed',
'count' => env('SERVER_PROCESS_COUNT', 2),
'user' => env('SERVER_PROCESS_USER', ''),
'group' => env('SERVER_PROCESS_GROUP', ''),
'pid_file' => runtime_path() . '/webman.pid',
'log_file' => runtime_path() . '/workerman.log',
'max_request' => 1000,
'stdout_file' => runtime_path() . '/logs/stdout.log',
'max_package_size' => 10*1024*1024
'listen' => 'http://0.0.0.0:8787',
'transport' => 'tcp',
'context' => [],
'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',
'status_file' => runtime_path() . '/webman.status',
'stdout_file' => runtime_path() . '/logs/stdout.log',
'max_request' => 1000,
'max_package_size' => 10 * 1024 * 1024
];

View File

@ -14,27 +14,27 @@
return [
'type' => 'file', // or redis or redis_cluster
'type' => 'file', // or redis or redis_cluster
'handler' => Webman\FileSessionHandler::class,
'handler' => Webman\Session\FileSessionHandler::class,
'config' => [
'file' => [
'save_path' => runtime_path() . '/sessions',
],
'redis' => [
'host' => '127.0.0.1',
'port' => 6379,
'auth' => '',
'timeout' => 2,
'database' => '',
'prefix' => 'redis_session_',
'host' => '127.0.0.1',
'port' => 6379,
'auth' => '',
'timeout' => 2,
'database' => '',
'prefix' => 'redis_session_',
],
'redis_cluster' => [
'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'],
'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'],
'timeout' => 2,
'auth' => '',
'prefix' => 'redis_session_',
'auth' => '',
'prefix' => 'redis_session_',
]
],

View File

@ -16,8 +16,8 @@
* 静态文件设置
*/
return [
'enable' => true, // 是否支持静态文件
'enable' => true, // 是否支持静态文件
'middleware' => [ // 静态文件中间件
support\middleware\StaticFile::class,
app\middleware\StaticFile::class,
],
];

View File

@ -18,15 +18,12 @@ I::::::::I Y:::::::::::Y UU:::::::::UU UU:::::::::UU
IIIIIIIIII YYYYYYYYYYYYY UUUUUUUUU UUUUUUUUU
EOF;
echo microtime(true).' 当前时间:'.date('Y-m-d H:i:s').PHP_EOL;
echo microtime(true).' 当前操作系统:'.PHP_OS.PHP_EOL;
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;
echo microtime(true) . ' 当前时间:' . date('Y-m-d H:i:s') . PHP_EOL;
echo microtime(true) . ' 当前操作系统:' . PHP_OS . PHP_EOL;
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;
// 定义目录
defined('ROOT_PATH') or define('ROOT_PATH', __DIR__);
@ -54,7 +51,7 @@ if (PHP_SAPI != 'cli') {
// 设置时区
date_default_timezone_set('Asia/Shanghai');
echo microtime(true).' 环境变量初始化完成!'.PHP_EOL.PHP_EOL;
echo microtime(true) . ' 环境变量初始化完成!' . PHP_EOL . PHP_EOL;
// 命令行参数
global $argv;

View File

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

View File

@ -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() 会被调用
*

View File

@ -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
{
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace IYUU\Library;
/**
@ -8,81 +9,42 @@ namespace IYUU\Library;
class IFile
{
private $resource = null; //文件资源句柄
/**
* @brief 构造函数,打开资源流,并独占锁定
* @param String $fileName 文件路径名
* @param String $mode 操作方式默认为读操作可供选择的项为r,r+,w+,w+,a,a+
* @param String $mode 操作方式默认为读操作可供选择的项为r,r+,w+,w+,a,a+
* @note $mod'r' 只读方式打开,将文件指针指向文件头
* 'r+' 读写方式打开,将文件指针指向文件头
* 'w' 写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。
* 'w+' 读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。
* 'a' 写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。
* 'a+' 读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。
* 'w' 写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。
* 'w+' 读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。
* 'a' 写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。
* 'a+' 读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。
*/
public function __construct($fileName, $mode='r')
public function __construct($fileName, $mode = 'r')
{
$dirName = dirname($fileName);
$dirName = dirname($fileName);
$baseName = basename($fileName);
//检查并创建文件夹
self::mkdir($dirName);
$this->resource = fopen($fileName, $mode.'b');
$this->resource = fopen($fileName, $mode . 'b');
if ($this->resource) {
flock($this->resource, LOCK_EX);
}
}
/**
* @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,23 +61,11 @@ 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 源文件路径
* @param String $to 目标文件路径
* @param String $mode 操作模式c:复制(默认); x:剪切(删除$from文件)
* @param String $to 目标文件路径
* @param String $mode 操作模式c:复制(默认); x:剪切(删除$from文件)
* @return bool 操作结果 true:成功; false:失败;
*/
public static function copy($from, $to, $mode = 'c')
@ -153,8 +103,8 @@ class IFile
/**
* @brief 删除$dir文件夹 或者 其下所有文件
* @param String $dir 文件路径
* @param bool $recursive 是否强制删除如果强制删除则递归删除该目录下的全部文件默认为false
* @param String $dir 文件路径
* @param bool $recursive 是否强制删除如果强制删除则递归删除该目录下的全部文件默认为false
* @return bool true:删除成功; false:删除失败;
*/
public static function rmdir($dir, $recursive = false)
@ -164,9 +114,7 @@ class IFile
if ($recursive == true) {
self::clearDir($dir);
return self::rmdir($dir, false);
}
//非强制删除
} //非强制删除
else {
if (rmdir($dir)) {
return true;
@ -178,9 +126,36 @@ 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 文件名
* @param String $fileName 文件名
* @return String|array $filetype 文件类型
* @note 如果文件不存在返回false,如果文件后缀名不在识别列表之内返回NULL对于docx及elsx格式文档识别在会出现识别为ZIP格式的错误这是office2007的bug目前尚未修复请谨慎使用
*/
@ -195,17 +170,17 @@ class IFile
if (!$fileRes) {
return false;
}
$bin= fread($fileRes, 2);
$bin = fread($fileRes, 2);
fclose($fileRes);
if ($bin != null) {
$strInfo = unpack("C2chars", $bin);
$typeCode = intval($strInfo['chars1'].$strInfo['chars2']);
$strInfo = unpack("C2chars", $bin);
$typeCode = intval($strInfo['chars1'] . $strInfo['chars2']);
$typelist = self::getTypeList();
foreach ($typelist as $val) {
if (strtolower($val[0]) == strtolower($typeCode)) {
if ($val[0] == 8075) {
return array('zip','docx','xlsx');
return array('zip', 'docx', 'xlsx');
} else {
return $val[1];
}
@ -222,28 +197,28 @@ class IFile
public static function getTypeList()
{
return array(
array('255216','jpg'),
array('13780','png'),
array('7173','gif'),
array('6677','bmp'),
array('6063','xml'),
array('60104','html'),
array('208207','xls/doc'),
array('8075','zip'),
array('8075','docx'),
array('8075','xlsx'),
array("8297","rar"),
array('255216', 'jpg'),
array('13780', 'png'),
array('7173', 'gif'),
array('6677', 'bmp'),
array('6063', 'xml'),
array('60104', 'html'),
array('208207', 'xls/doc'),
array('8075', 'zip'),
array('8075', 'docx'),
array('8075', 'xlsx'),
array("8297", "rar"),
);
}
/**
* @brief 获取文件大小
* @param String $fileName 文件名
* @param String $fileName 文件名
* @return Int 文件大小的字节数,如果文件无效则返回 NULL
*/
public static function getFileSize($fileName)
{
return is_file($fileName) ? filesize($fileName):null;
return is_file($fileName) ? filesize($fileName) : null;
}
/**
@ -255,9 +230,9 @@ class IFile
{
if (is_dir($dir)) {
$isEmpty = true;
$dirRes = opendir($dir);
$dirRes = opendir($dir);
while (false !== ($fileName = readdir($dirRes))) {
if ($fileName!='.' && $fileName!='..') {
if ($fileName != '.' && $fileName != '..') {
$isEmpty = false;
break;
}
@ -268,17 +243,9 @@ class IFile
return false;
}
/**
* @brief 释放文件锁定
*/
public function save()
{
flock($this->resource, LOCK_UN);
}
/**
* @brief 获取文件扩展名
* @param String $fileName 文件名
* @param String $fileName 文件名
* @return String 文件后缀名
*/
public static function getFileSuffix($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 析构函数,释放文件连接句柄
*/

View File

@ -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;
/**
* 初始化
@ -83,7 +84,7 @@ class Rpc
self::$workingMode = isset($config['workingMode']) ? 0 : 1;
//初始化下载种子的存放目录
self::$torrentDir = TORRENT_PATH . DS . $site . DS;
self::$torrentDir = TORRENT_PATH . DS . $site . DS;
//初始化watch目录
if (empty(self::$clients['watch'])) {
@ -120,9 +121,9 @@ class Rpc
static::$links = array();
//watch监控目录未设置用户名密码未设置直接报错
if (empty(self::$clients['watch'])) {
die("clients_".self::$clients['name']." 用户名或密码未配置下载器的watch监控目录未配置".PHP_EOL.PHP_EOL);
die("clients_" . self::$clients['name'] . " 用户名或密码未配置下载器的watch监控目录未配置" . PHP_EOL . PHP_EOL);
}
echo "clients_".self::$clients['name']." 用户名或密码未配置切换为watch模式".PHP_EOL.PHP_EOL;
echo "clients_" . self::$clients['name'] . " 用户名或密码未配置切换为watch模式" . PHP_EOL . PHP_EOL;
self::$workingMode = 0;
return false;
}
@ -134,9 +135,9 @@ class Rpc
static::$links['type'] = self::$clients['type'];
static::$links['root_folder'] = self::$clients['root_folder'] ?? 1;
$result = $client->status();
print self::$clients['type'].''.self::$clients['host']." Rpc连接 [{$result}]".PHP_EOL;
print self::$clients['type'] . '' . self::$clients['host'] . " Rpc连接 [{$result}]" . PHP_EOL;
} catch (\Exception $e) {
die(__FILE__ . ' LINE:' . __LINE__ . '[连接错误] '. self::$clients['host'] . ' ' . $e->getMessage() . PHP_EOL);
die(__FILE__ . ' LINE:' . __LINE__ . '[连接错误] ' . self::$clients['host'] . ' ' . $e->getMessage() . PHP_EOL);
}
}
return true;
@ -148,26 +149,26 @@ class Rpc
* Array
* (
* [id] => 118632
* [h1] => CCTV5+ 2019 ATP Men's Tennis Final 20191115B HDTV 1080i H264-HDxxx
* [title] => 央视体育赛事频道 2019年ATP男子网球年终总决赛 单打小组赛 纳达尔VS西西帕斯 20191115[优惠剩余时间4时13分]
* [details] => https://XXX.me/details.php?id=118632
* [download] => https://XXX.me/download.php?id=118632
* [filename] => 118632.torrent
* [type] => 0
* [sticky] => 1
* [time] => Array
* (
* [0] => "2019-11-16 20:41:53">4时13分
* [1] => "2019-11-16 14:41:53">1<br />46
* )
* [comments] => 0
* [size] => 5232.64MB
* [seeders] => 69
* [leechers] => 10
* [completed] => 93
* [percentage] => 100%
* [owner] => 匿名
* )
* [h1] => CCTV5+ 2019 ATP Men's Tennis Final 20191115B HDTV 1080i H264-HDxxx
* [title] => 央视体育赛事频道 2019年ATP男子网球年终总决赛 单打小组赛 纳达尔VS西西帕斯 20191115[优惠剩余时间4时13分]
* [details] => https://XXX.me/details.php?id=118632
* [download] => https://XXX.me/download.php?id=118632
* [filename] => 118632.torrent
* [type] => 0
* [sticky] => 1
* [time] => Array
* (
* [0] => "2019-11-16 20:41:53">4时13分
* [1] => "2019-11-16 14:41:53">1<br />46
* )
* [comments] => 0
* [size] => 5232.64MB
* [seeders] => 69
* [leechers] => 10
* [completed] => 93
* [percentage] => 100%
* [owner] => 匿名
* )
* @return mixed
*/
public static function call(array $data = array())
@ -175,9 +176,9 @@ class Rpc
// 首次运行锁 开始
$LOCK = self::$torrentDir . self::$site . '.lock';
if (!is_file($LOCK)) {
echo "系统未检测到首次运行锁({$LOCK}),将会启动账号保护逻辑。".PHP_EOL;
echo "系统未检测到首次运行锁({$LOCK}),将会启动账号保护逻辑。" . PHP_EOL;
$max_downloads = 2;
echo "为保护账号安全,首次运行仅处理前{$max_downloads}个种子,其余全部忽略;下次运行,会继续下载新种。".PHP_EOL;
echo "为保护账号安全,首次运行仅处理前{$max_downloads}个种子,其余全部忽略;下次运行,会继续下载新种。" . PHP_EOL;
file_put_contents($LOCK, date('Y-m-d H:i:s'));
foreach ($data as $k => $torrent) {
if ($k < $max_downloads) {
@ -191,15 +192,15 @@ class Rpc
foreach ($data as $key => $value) {
// 控制台打印
echo '主标题:'.$value['h1'].PHP_EOL;
echo '副标题:'.$value['title'].PHP_EOL;
echo '详情页:'.$value['details'].PHP_EOL;
echo '主标题:' . $value['h1'] . PHP_EOL;
echo '副标题:' . $value['title'] . PHP_EOL;
echo '详情页:' . $value['details'] . PHP_EOL;
if ($value['type'] != 0) {
echo "-----非免费,已忽略!".PHP_EOL.PHP_EOL;
echo "-----非免费,已忽略!" . PHP_EOL . PHP_EOL;
continue;
}
if (isset($value['hr']) && ($value['hr'] == 1)) {
echo "-----HR种子已忽略".PHP_EOL.PHP_EOL;
echo "-----HR种子已忽略" . PHP_EOL . PHP_EOL;
continue;
}
// 保存的文件名
@ -209,57 +210,57 @@ class Rpc
// 种子完整存放路径
$torrentFile = self::$torrentDir . $filename;
if (is_file($torrentFile)) {
$fileSize = filesize($torrentFile); //失败会返回false 或 00代表上次下载失败
$fileSize = filesize($torrentFile); //失败会返回false 或 00代表上次下载失败
if (!empty($fileSize)) {
//种子已经存在
echo '-----存在旧种子:'.$filename.PHP_EOL.PHP_EOL;
echo '-----存在旧种子:' . $filename . PHP_EOL . PHP_EOL;
continue;
}
// 删除下载错误的文件
IFile::unlink($torrentFile);
}
// 调用过滤函数
$filter = empty(self::$conf['filter']) ? [] : self::$conf['filter'];
$isFilter = filter($filter, $value);
if (is_string($isFilter)) {
echo "-----" .$isFilter. PHP_EOL.PHP_EOL;
echo "-----" . $isFilter . PHP_EOL . PHP_EOL;
continue;
}
//优先级最高:过滤器数据目录
$downloadsDir = !empty($filter['downloadsDir']) ? $filter['downloadsDir'] : self::$downloadsDir;
//种子不存在
echo '正在下载新种子... '.$value['download'].PHP_EOL;
echo '正在下载新种子... ' . $value['download'] . PHP_EOL;
// 创建文件、下载种子以二进制写入
$content = download($value['download'], self::$cookies, self::$userAgent, self::$method);
#cli($content);
if (strpos($content, '第一次下载提示') !== false) {
die('当前站点触发第一次下载提示请手动下载1个种子然后更新cookie'.PHP_EOL);
die('当前站点触发第一次下载提示请手动下载1个种子然后更新cookie' . PHP_EOL);
}
// 成功返回写入字节数失败返回false
$worldsnum = file_put_contents($torrentFile, $content);
if (is_bool($worldsnum)) {
print "种子下载失败!!!".PHP_EOL.PHP_EOL;
print "种子下载失败!!!" . PHP_EOL . PHP_EOL;
IFile::unlink($torrentFile);
continue;
} else {
print "成功下载种子" . $filename . ',共计:' . $worldsnum . "字节".PHP_EOL;
print "成功下载种子" . $filename . ',共计:' . $worldsnum . "字节" . PHP_EOL;
sleep(mt_rand(2, 10));
$ret = null;
switch ((int)self::$workingMode) {
case 0: //watch下载模式
case 0: //watch下载模式
// 复制到watch目录
if (dirname($torrentFile) !== dirname($torrentFileTo)) {
copy($torrentFile, $torrentFileTo);
}
if (is_file($torrentFileTo)) {
print "********watch模式下载任务添加成功.".PHP_EOL.PHP_EOL;
print "********watch模式下载任务添加成功." . PHP_EOL . PHP_EOL;
$ret = true;
} else {
print "-----watch模式下载任务添加失败!!!".PHP_EOL.PHP_EOL;
print "-----watch模式下载任务添加失败!!!" . PHP_EOL . PHP_EOL;
}
break;
case 1: //Rpc下载模式
case 1: //Rpc下载模式
// 下载任务的可选参数
$extra_options = array();
$type = self::$links['type'];
@ -271,7 +272,7 @@ class Rpc
case 'qBittorrent':
$extra_options['name'] = 'torrents';
$extra_options['filename'] = $filename;
$extra_options['autoTMM'] = 'false'; //关闭自动种子管理
$extra_options['autoTMM'] = 'false'; //关闭自动种子管理
$ret = static::$links['rpc']->add_torrent($content, $downloadsDir, $extra_options);
break;
default:

View File

@ -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选择器
*
@ -85,7 +56,7 @@ class Selector
// 如果加载的不是之前的HTML内容替换一下验证标识
if (self::$dom_auth !== md5($html)) {
self::$dom_auth = md5($html);
@self::$dom->loadHTML('<?xml encoding="UTF-8">'.$html);
@self::$dom->loadHTML('<?xml encoding="UTF-8">' . $html);
// 清空 libxml 错误缓冲
libxml_clear_errors();
self::$xpath = new DOMXpath(self::$dom);
@ -111,15 +82,14 @@ 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 {
// 保留nodeValue里的html符号给children二次提取
$content = self::$dom->saveXml($element);
//$content = trim(self::$dom->saveHtml($element));
$content = preg_replace(array("#^<{$nodeName}.*>#isU","#</{$nodeName}>$#isU"), array('', ''), $content);
$content = preg_replace(array("#^<{$nodeName}.*>#isU", "#</{$nodeName}>$#isU"), array('', ''), $content);
}
}
$result[] = $content;
@ -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
$xquery .= "[@id='" . substr($s, 1) . "']";
} // CLASSES
elseif ($s[0] == '.') {
if ($delimiter_before) {
$xquery .= '*';
}
// CLASS用模糊查询
$xquery .= "[contains(@class,'".substr($s, 1)."')]";
}
// ATTRIBUTES
$xquery .= "[contains(@class,'" . substr($s, 1) . "')]";
} // 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'");
}
@ -284,7 +243,7 @@ class Selector
return $queries;
}
$special_chars = array('>',' ');
$special_chars = array('>', ' ');
$special_chars_mapping = array();
$strlen = mb_strlen($query);
$class_chars = array('.', '-');
@ -293,7 +252,7 @@ class Selector
// split multibyte string
// http://code.google.com/p/phpquery/issues/detail?id=76
$_query = array();
for ($i=0; $i<$strlen; $i++) {
for ($i = 0; $i < $strlen; $i++) {
$_query[] = mb_substr($query, $i, 1);
}
$query = $_query;
@ -309,46 +268,40 @@ class Selector
$i++;
}
$queries[] = $tmp;
}
// IDs
} // IDs
elseif ($c == '#') {
$i++;
while (isset($query[$i]) && (self::is_char($query[$i]) || $query[$i] == '-')) {
$tmp .= $query[$i];
$i++;
}
$queries[] = '#'.$tmp;
}
// SPECIAL CHARS
$queries[] = '#' . $tmp;
} // SPECIAL CHARS
elseif (in_array($c, $special_chars)) {
$queries[] = $c;
$i++;
// MAPPED SPECIAL MULTICHARS
// MAPPED SPECIAL MULTICHARS
// } 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;
@ -396,15 +347,14 @@ class Selector
$stack++;
} elseif ($query[$i] == ']') {
$stack--;
if (! $stack) {
if (!$stack) {
break;
}
}
}
$queries[] = $tmp;
$i++;
}
// PSEUDO CLASSES
} // PSEUDO CLASSES
elseif ($c == ':') {
$stack = 1;
$tmp .= $query[$i++];
@ -422,7 +372,7 @@ class Selector
$stack++;
} elseif ($query[$i] == ')') {
$stack--;
if (! $stack) {
if (!$stack) {
break;
}
}
@ -469,6 +419,36 @@ class Selector
*/
protected static function is_regexp($pattern)
{
return in_array($pattern[ mb_strlen($pattern)-1 ], array('^','*','$'));
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);
}
}

View File

@ -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
@ -156,32 +140,65 @@ class Table
}
/**
* 设置输出表格的样式
* 输出表格
* @access public
* @param string $style 样式名
* @return void
* @param array $dataList 表格数据
* @return string
*/
public function setStyle($style)
public function render($dataList = [])
{
$this->style = isset($this->format[$style]) ? $style : 'default';
if ($dataList) {
$this->setRows($dataList);
}
// 输出头部
$content = $this->renderHeader();
$style = $this->getStyle('cell');
if ($this->rows) {
foreach ($this->rows as $row) {
if (is_string($row) && '-' === $row) {
$content .= $this->renderSeparator('middle');
} elseif (is_scalar($row)) {
$content .= $this->renderSeparator('cross-top');
$array = str_pad($row, 3 * (count($this->colWidth) - 1) + array_reduce($this->colWidth, function ($a, $b) {
return $a + $b;
}));
$content .= $style[0] . ' ' . $array . ' ' . $style[3] . PHP_EOL;
$content .= $this->renderSeparator('cross-bottom');
} else {
$array = [];
foreach ($row as $key => $val) {
$array[] = ' ' . str_pad($val, $this->colWidth[$key], ' ', $this->cellAlign);
}
$content .= $style[0] . implode(' ' . $style[2], $array) . ' ' . $style[3] . PHP_EOL;
}
}
}
$content .= $this->renderSeparator('bottom');
return $content;
}
/**
* 输出分隔行
* 设置输出表格数据 及对齐方式
* @access public
* @param string $pos 位置
* @return string
* @param array $rows 要输出的表格数据(二维数组)
* @param int $align 对齐方式 默认1 ALGIN_LEFT 0 ALIGN_RIGHT 2 ALIGN_CENTER
* @return void
*/
protected function renderSeparator($pos)
public function setRows($rows, $align = self::ALIGN_LEFT)
{
$style = $this->getStyle($pos);
$array = [];
$this->rows = $rows;
$this->cellAlign = $align;
foreach ($this->colWidth as $width) {
$array[] = str_repeat($style[1], $width + 2);
foreach ($rows as $row) {
$this->checkColWidth($row);
}
return $style[0] . implode($style[2], $array) . $style[3] . PHP_EOL;
}
/**
@ -221,47 +238,31 @@ class Table
}
/**
* 输出表格
* 设置输出表格的样式
* @access public
* @param array $dataList 表格数据
* @param string $style 样式名
* @return void
*/
public function setStyle($style)
{
$this->style = isset($this->format[$style]) ? $style : 'default';
}
/**
* 输出分隔行
* @access public
* @param string $pos 位置
* @return string
*/
public function render($dataList = [])
protected function renderSeparator($pos)
{
if ($dataList) {
$this->setRows($dataList);
$style = $this->getStyle($pos);
$array = [];
foreach ($this->colWidth as $width) {
$array[] = str_repeat($style[1], $width + 2);
}
// 输出头部
$content = $this->renderHeader();
$style = $this->getStyle('cell');
if ($this->rows) {
foreach ($this->rows as $row) {
if (is_string($row) && '-' === $row) {
$content .= $this->renderSeparator('middle');
} elseif (is_scalar($row)) {
$content .= $this->renderSeparator('cross-top');
$array = str_pad($row, 3 * (count($this->colWidth) - 1) + array_reduce($this->colWidth, function ($a, $b) {
return $a + $b;
}));
$content .= $style[0] . ' ' . $array . ' ' . $style[3] . PHP_EOL;
$content .= $this->renderSeparator('cross-bottom');
} else {
$array = [];
foreach ($row as $key => $val) {
$array[] = ' ' . str_pad($val, $this->colWidth[$key], ' ', $this->cellAlign);
}
$content .= $style[0] . implode(' ' . $style[2], $array) . ' ' . $style[3] . PHP_EOL;
}
}
}
$content .= $this->renderSeparator('bottom');
return $content;
return $style[0] . implode($style[2], $array) . $style[3] . PHP_EOL;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
<?php
namespace IYUU\Reseed;
use app\domain\ConfigParser\Move as domainMove;
@ -29,9 +30,10 @@ class MoveTorrent extends AutoReseed
* @var array
*/
protected static $wechatMsg = array(
'MoveSuccess' => 0, // 移动成功
'MoveError' => 0, // 移动失败
'MoveSuccess' => 0, // 移动成功
'MoveError' => 0, // 移动失败
);
/**
* 初始化
*/
@ -53,7 +55,7 @@ class MoveTorrent extends AutoReseed
self::$conf = domainMove::parser($cron_name);
// 用户选择的下载器
self::$clients = self::$conf['clients'];
echo microtime(true).' 命令行参数解析完成!'.PHP_EOL;
echo microtime(true) . ' 命令行参数解析完成!' . PHP_EOL;
}
/**
@ -75,14 +77,14 @@ class MoveTorrent extends AutoReseed
//遍历客户端
foreach (self::$links as $k => $v) {
if ($k === self::$conf['to_clients']['uuid']) {
echo "clients_".$k."是目标转移客户端,避免冲突,已跳过!".PHP_EOL.PHP_EOL;
echo "clients_" . $k . "是目标转移客户端,避免冲突,已跳过!" . PHP_EOL . PHP_EOL;
continue;
}
if (empty(self::$links[$k])) {
echo "clients_".$k." 用户名或密码未配置,已跳过".PHP_EOL.PHP_EOL;
echo "clients_" . $k . " 用户名或密码未配置,已跳过" . PHP_EOL . PHP_EOL;
continue;
}
echo "正在从下载器 clients_".$k." 获取种子哈希……".PHP_EOL;
echo "正在从下载器 clients_" . $k . " 获取种子哈希……" . PHP_EOL;
$move = []; // 客户端做种列表 传址
$hashArray = static::getRpc($k)->all($move);
if (empty($hashArray)) {
@ -91,18 +93,18 @@ class MoveTorrent extends AutoReseed
} else {
$infohash_Dir = $hashArray['hashString'];
// 写日志
static::wLog($hashArray, 'move'.$k);
static::wLog($hashArray, 'move' . $k);
}
// 前置过滤移除转移成功的hash
$rs = self::hashFilter($infohash_Dir);
if ($rs) {
echo "clients_".$k." 全部转移成功,本次无需转移!".PHP_EOL.PHP_EOL;
echo "clients_" . $k . " 全部转移成功,本次无需转移!" . PHP_EOL . PHP_EOL;
continue;
}
$qBittorrent_version_lg_4_4 = false;
if ($v['type'] == 'qBittorrent') {
$arr = explode('.', ltrim($version, "v"), 3);
if (count($arr) > 2 && ($arr[0] == '4' && $arr[1] >= '4' || $arr[0] > '4')) {
if (count($arr) > 2 && ($arr[0] == '4' && $arr[1] >= '4' || $arr[0] > '4')) {
global $qBittorrent_version_lg_4_4;
$qBittorrent_version_lg_4_4 = true;
}
@ -114,13 +116,13 @@ class MoveTorrent extends AutoReseed
continue;
}
// 做种实际路径与相对路径之间互转
echo '转换前:'.$downloadDir.PHP_EOL;
echo '转换前:' . $downloadDir . PHP_EOL;
$downloadDir = self::pathReplace($downloadDir);
echo '转换后:'.$downloadDir.PHP_EOL;
$help_msg = 'IYUU自动转移做种客户端--使用教程'.PHP_EOL.'https://www.iyuu.cn/archives/451/'.PHP_EOL.'https://www.iyuu.cn/archives/465/'.PHP_EOL;
echo '转换后:' . $downloadDir . PHP_EOL;
$help_msg = 'IYUU自动转移做种客户端--使用教程' . PHP_EOL . 'https://www.iyuu.cn/archives/451/' . PHP_EOL . 'https://www.iyuu.cn/archives/465/' . PHP_EOL;
if (is_null($downloadDir)) {
echo $help_msg;
die("路径转换参数配置错误,请重新配置!!!".PHP_EOL);
die("路径转换参数配置错误,请重新配置!!!" . PHP_EOL);
}
// 种子目录:脚本要能够读取到
$path = self::$links[$k]['BT_backup'];
@ -144,26 +146,26 @@ class MoveTorrent extends AutoReseed
case 'qBittorrent':
if (empty($path)) {
echo $help_msg;
die("clients_".$k." IYUUPlus内下载器未设置种子目录无法完成转移");
die("clients_" . $k . " IYUUPlus内下载器未设置种子目录无法完成转移");
}
$torrentPath = $path .DS. $info_hash . '.torrent';
$fast_resumePath = $path .DS. $info_hash . '.fastresume';
$torrentPath = $path . DS . $info_hash . '.torrent';
$fast_resumePath = $path . DS . $info_hash . '.fastresume';
$torrentDelete = $info_hash;
break;
default:
break;
}
if (!is_file($torrentPath)) {
$v1_path = $path .DS. $move[$info_hash]['infohash_v1'] . '.torrent';
$v1_path = $path . DS . $move[$info_hash]['infohash_v1'] . '.torrent';
if (is_file($v1_path)) {
$torrentPath = $v1_path;
$fast_resumePath = $path .DS. $move[$info_hash]['infohash_v1'] . '.torrent';
$fast_resumePath = $path . DS . $move[$info_hash]['infohash_v1'] . '.torrent';
} else {
echo $help_msg;
die("clients_".$k." 的`{$move[$info_hash]['name']}`,种子文件`{$torrentPath}`不存在,无法完成转移!");
die("clients_" . $k . " 的`{$move[$info_hash]['name']}`,种子文件`{$torrentPath}`不存在,无法完成转移!");
}
}
echo '存在种子:'.$torrentPath.PHP_EOL;
echo '存在种子:' . $torrentPath . PHP_EOL;
$torrent = file_get_contents($torrentPath);
$parsed_torrent = [];
try {
@ -172,11 +174,12 @@ class MoveTorrent extends AutoReseed
if (empty($parsed_torrent['announce'])) {
$needPatchTorrent = true;
}
} catch (ParseException $e) {}
} catch (ParseException $e) {
}
if ($needPatchTorrent) {
echo '未发现tracker信息尝试补充tracker信息...'.PHP_EOL;
echo '未发现tracker信息尝试补充tracker信息...' . PHP_EOL;
if (empty($parsed_torrent)) {
die("clients_".$k." 的`{$move[$info_hash]['name']}`,种子文件`{$torrentPath}`解析失败,无法完成转移!");
die("clients_" . $k . " 的`{$move[$info_hash]['name']}`,种子文件`{$torrentPath}`解析失败,无法完成转移!");
}
if (empty($parsed_torrent['announce'])) {
if (isset($move[$info_hash]['tracker'])) {
@ -191,7 +194,7 @@ class MoveTorrent extends AutoReseed
global $parsed_fast_resume;
$parsed_fast_resume = Bencode::load($fast_resumePath);
} catch (ParseException $e) {
die("clients_".$k." 的`{$move[$info_hash]['name']}`resume文件`{$fast_resumePath}`解析失败`{$e->getMessage()}`,无法完成转移!");
die("clients_" . $k . " 的`{$move[$info_hash]['name']}`resume文件`{$fast_resumePath}`解析失败`{$e->getMessage()}`,无法完成转移!");
}
$trackers = $parsed_fast_resume['trackers'];
if (count($trackers) > 0 && !empty($trackers[0])) {
@ -199,14 +202,14 @@ class MoveTorrent extends AutoReseed
$parsed_torrent['announce'] = $trackers[0][0];
}
} else {
die("clients_".$k." 的`{$move[$info_hash]['name']}`resume文件`{$fast_resumePath}`不包含tracker地址无法完成转移");
die("clients_" . $k . " 的`{$move[$info_hash]['name']}`resume文件`{$fast_resumePath}`不包含tracker地址无法完成转移");
}
}
}
$torrent = Bencode::encode($parsed_torrent);
}
// 正式开始转移
echo "种子已推送给下载器,正在转移做种...".PHP_EOL;
echo "种子已推送给下载器,正在转移做种..." . PHP_EOL;
// 目标下载器类型
$clientKey = self::$conf['to_clients']['uuid'];
@ -225,7 +228,7 @@ class MoveTorrent extends AutoReseed
/**
* 转移成功的种子写日志
*/
$log = $info_hash.PHP_EOL.$torrentPath.PHP_EOL.$downloadDir.PHP_EOL.PHP_EOL;
$log = $info_hash . PHP_EOL . $torrentPath . PHP_EOL . $downloadDir . PHP_EOL . PHP_EOL;
if ($ret) {
//转移成功时,删除做种,不删资源
if (isset(self::$conf['delete_torrent']) && self::$conf['delete_torrent']) {
@ -233,11 +236,11 @@ class MoveTorrent extends AutoReseed
}
// 转移成功的种子以infohash为文件名写入缓存
static::wLog($log, $info_hash, self::$cacheMove);
static::wLog($log, 'MoveSuccess'.$k);
static::wLog($log, 'MoveSuccess' . $k);
static::$wechatMsg['MoveSuccess']++;
} else {
// 失败的种子
static::wLog($log, 'MoveError'.$k);
static::wLog($log, 'MoveError' . $k);
static::$wechatMsg['MoveError']++;
}
}
@ -246,15 +249,15 @@ class MoveTorrent extends AutoReseed
/**
* 过滤已转移的种子hash
* @param array $infohash_Dir infohash与路径对应的字典
* @param array $infohash_Dir infohash与路径对应的字典
* @return bool true 过滤 | false 不过滤
*/
private static function hashFilter(&$infohash_Dir = array())
{
foreach ($infohash_Dir as $info_hash => $dir) {
if (is_file(self::$cacheMove . $info_hash.'.txt')) {
if (is_file(self::$cacheMove . $info_hash . '.txt')) {
unset($infohash_Dir[$info_hash]);
echo '-------当前种子上次已成功转移,前置过滤已跳过! 如需再次转移,可以清理转移缓存。' .PHP_EOL.PHP_EOL;
echo '-------当前种子上次已成功转移,前置过滤已跳过! 如需再次转移,可以清理转移缓存。' . PHP_EOL . PHP_EOL;
}
}
return empty($infohash_Dir) ? true : false;
@ -279,19 +282,19 @@ class MoveTorrent extends AutoReseed
//选择器
if (\is_array($path_selector)) {
foreach ($path_selector as $pathName) {
if (strpos($path, $pathName)===0) { // 没用$path == $key判断是为了提高兼容性
if (strpos($path, $pathName) === 0) { // 没用$path == $key判断是为了提高兼容性
return false;
}
}
echo '已跳过!转移选择器未匹配到:'.$path.PHP_EOL;
echo '已跳过!转移选择器未匹配到:' . $path . PHP_EOL;
return true;
}
} elseif (\is_null($path_selector)) {
//过滤器
if (\is_array($path_filter)) {
foreach ($path_filter as $pathName) {
if (strpos($path, $pathName)===0) { // 没用$path == $key判断是为了提高兼容性
echo '已跳过!转移过滤器匹配到:'.$path.PHP_EOL;
if (strpos($path, $pathName) === 0) { // 没用$path == $key判断是为了提高兼容性
echo '已跳过!转移过滤器匹配到:' . $path . PHP_EOL;
return true;
}
}
@ -302,18 +305,18 @@ class MoveTorrent extends AutoReseed
if (\is_array($path_filter) && \is_array($path_selector)) {
//先过滤器
foreach ($path_filter as $pathName) {
if (strpos($path, $pathName)===0) {
echo '已跳过!转移过滤器匹配到:'.$path.PHP_EOL;
if (strpos($path, $pathName) === 0) {
echo '已跳过!转移过滤器匹配到:' . $path . PHP_EOL;
return true;
}
}
//后选择器
foreach ($path_selector as $pathName) {
if (strpos($path, $pathName)===0) {
if (strpos($path, $pathName) === 0) {
return false;
}
}
echo '已跳过!转移选择器未匹配到:'.$path.PHP_EOL;
echo '已跳过!转移选择器未匹配到:' . $path . PHP_EOL;
return true;
}
}
@ -333,21 +336,21 @@ class MoveTorrent extends AutoReseed
switch ($type) {
case 1: // 减
foreach ($pathArray as $key => $val) {
if (strpos($path, $key)===0) {
if (strpos($path, $key) === 0) {
return substr($path, strlen($key));
}
}
break;
case 2: // 加
foreach ($pathArray as $key => $val) {
if (strpos($path, $key)===0) { // 没用$path == $key判断是为了提高兼容性
if (strpos($path, $key) === 0) { // 没用$path == $key判断是为了提高兼容性
return $val . $path;
}
}
break;
case 3: // 替换
foreach ($pathArray as $key => $val) {
if (strpos($path, $key)===0) { // 没用$path == $key判断是为了提高兼容性
if (strpos($path, $key) === 0) { // 没用$path == $key判断是为了提高兼容性
return $val . substr($path, strlen($key));
}
}
@ -395,19 +398,19 @@ class MoveTorrent extends AutoReseed
}
$br = PHP_EOL;
$text = 'IYUU转移任务-统计报表';
$desp = '### 版本号:'. IYUU_VERSION() . $br;
$desp = '### 版本号:' . IYUU_VERSION() . $br;
// 移动做种
if (static::$wechatMsg['MoveSuccess'] || static::$wechatMsg['MoveError']) {
$desp .= $br.'----------'.$br;
$desp .= '**移动成功:'.static::$wechatMsg['MoveSuccess']. '** [会把hash加入移动缓存]' .$br;
$desp .= '**移动失败:'.static::$wechatMsg['MoveError']. '** [解决错误提示,可以重试]' .$br;
$desp .= '**如需重新移动,请删除 ./torrent/cachemove 移动缓存。**'.$br;
$desp .= $br . '----------' . $br;
$desp .= '**移动成功:' . static::$wechatMsg['MoveSuccess'] . '** [会把hash加入移动缓存]' . $br;
$desp .= '**移动失败:' . static::$wechatMsg['MoveError'] . '** [解决错误提示,可以重试]' . $br;
$desp .= '**如需重新移动,请删除 ./torrent/cachemove 移动缓存。**' . $br;
} else {
$desp .= $br.'----------'.$br;
$desp .= $br.'转移任务完成,未发现种子需要转移'.$br;
$desp .= $br.'----------'.$br;
$desp .= $br . '----------' . $br;
$desp .= $br . '转移任务完成,未发现种子需要转移' . $br;
$desp .= $br . '----------' . $br;
}
$desp .= $br.'*此消息将在3天后过期*。';
$desp .= $br . '*此消息将在3天后过期*。';
return static::ff($text, $desp);
}
}

View File

@ -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的关联
@ -62,15 +49,15 @@ class Oauth
}
if (isset(self::$conf['sites'][$site]['passkey']) && self::$conf['sites'][$site]['passkey'] && isset(self::$conf['sites'][$site]['id']) && self::$conf['sites'][$site]['id']) {
$user_id = self::$conf['sites'][$site]['id'];
$passkey = self::$conf['sites'][$site]['passkey'];
$passkey = self::$conf['sites'][$site]['passkey'];
$curl = new Curl();
$curl->setOpt(CURLOPT_SSL_VERIFYPEER, false);
$data = [
'token' => $token,
'id' => $user_id,
'passkey'=> sha1($passkey), // 避免泄露用户passkey秘钥
'site' => $site,
'token' => $token,
'id' => $user_id,
'passkey' => sha1($passkey), // 避免泄露用户passkey秘钥
'site' => $site,
];
$res = $curl->get($apiUrl, $data);
cli($res->response);
@ -85,13 +72,27 @@ class Oauth
echo $msg . PHP_EOL;
}
} else {
echo $site.'合作站点参数配置不完整请同时填写passkey和用户id。' . PHP_EOL;
echo '合作站点鉴权配置请查阅https://www.iyuu.cn/archives/337/'. PHP_EOL. PHP_EOL;
echo $site . '合作站点参数配置不完整请同时填写passkey和用户id。' . PHP_EOL;
echo '合作站点鉴权配置请查阅https://www.iyuu.cn/archives/337/' . PHP_EOL . PHP_EOL;
}
}
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 作用:减少对服务器请求,跳过鉴权提示信息;

View File

@ -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,111 +56,24 @@ abstract class AbstractRss
* passkey
*/
public $passkey = '';
/**
* 种子ID正则
* @var string
*/
public $torrent_id_regex = '/id=(\d+)/i';
/**
* 运行时解析的配置
* @var array
*/
protected static $conf = [];
/**
* 站点名转换为文件名,所使用的映射表
*/
const SITENAME_TO_FILENAME_MAP = Constant::SITENAME_TO_FILENAME_MAP;
/**
* 实例化
* @param string $uuid 任务标识
* @return mixed 返回站点的rss解码实例
*/
public static function getInstance($uuid)
{
$filename = self::getCliInput($uuid);
// 转小写
$filename = strtolower($filename);
$file = __DIR__ . DIRECTORY_SEPARATOR .$filename.'.php';
if (!is_file($file)) {
die($file.' 文件不存在');
}
$className = 'IYUU\\Rss\\'.$filename;
if (class_exists($className)) {
echo $filename." RSS解码类正在实例化".PHP_EOL;
return new $className();
} else {
die($filename.' RSS解码类不存在');
}
}
/**
* 解析命令行参数 【静态方法】
* @param string $uuid 任务标识
* @return string 类文件名
*/
private static function getCliInput($uuid)
{
self::$conf = domainRss::parser($uuid);
if (empty(self::$conf)) {
die('当前任务不存在或者未开启。'.PHP_EOL);
}
if (empty(self::$conf['site'])) {
die('解析计划任务失败:用户未配置的站点。'.PHP_EOL);
}
if (empty(self::$conf['sites'])) {
die('解析计划任务失败:用户配置的站点,当前不受支持。'.PHP_EOL);
}
if (empty(self::$conf['clients'])) {
die('解析计划任务失败当前下载器可能已经删除请编辑RSS下载任务重选下载器。'.PHP_EOL);
}
echo microtime(true).' 命令行参数解析完成!'.PHP_EOL;
//cli(self::$conf);
$siteName = self::$conf['site']['name'];
return static::getFileName($siteName);
}
/**
* 从站点名解析出类名(文件名)
* @param string $site_name
* @return string 类文件名
*/
public static function getFileName(string $site_name):string
{
return isset(self::SITENAME_TO_FILENAME_MAP[$site_name]) ? self::SITENAME_TO_FILENAME_MAP[$site_name] : $site_name;
}
/**
* 从类名解析出站点名(配置里站点的键名)
* @param string $class_name
* @return string
*/
public static function getSiteName(string $class_name):string
{
$classname_to_sitename_map = array_flip(static::SITENAME_TO_FILENAME_MAP);
if (array_key_exists($class_name, $classname_to_sitename_map)) {
$siteName = $classname_to_sitename_map[$class_name];
} else {
$siteName = $class_name;
}
return $siteName;
}
/**
* 构造方法,配置应用信息
* @param bool $init 是否初始化domainRss获取全部站点名时候需要到
* @param bool $init 是否初始化domainRss获取全部站点名时候需要到
*/
final public function __construct($init = true)
{
if ($init) {
echo $this->site." 正在初始化RSS配置...". PHP_EOL;
echo $this->site . " 正在初始化RSS配置..." . PHP_EOL;
//cli(self::$conf);
$this->_initialize();
$this->init();
echo $this->site." RSS解码类实例化成功".PHP_EOL;
echo $this->site . " RSS解码类实例化成功" . PHP_EOL;
}
}
@ -173,6 +96,30 @@ abstract class AbstractRss
$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;
}
/**
* 初始化 第二步,子类可以重写此方法
*/
@ -182,24 +129,208 @@ abstract class AbstractRss
$config = static::$conf['site'];
$this->passkey = !empty($config['passkey']) ? $config['passkey'] : '';
if (empty($this->passkey)) {
die($this->site.' 没有配置密钥,初始化错误。'.PHP_EOL);
die($this->site . ' 没有配置密钥,初始化错误。' . PHP_EOL);
}
}
/**
* 过滤XML文档中不需要的元素子类可以重写此方法
* @param DOMDocument $item
* @return DOMDocument | DOMNode
* 实例化
* @param string $uuid 任务标识
* @return mixed 返回站点的rss解码实例
*/
protected function filterNexusPHP($item)
public static function getInstance($uuid)
{
$node = $item->getElementsByTagName('description')->item(0);
if ($node != null) {
$item->removeChild($node);
$filename = self::getCliInput($uuid);
// 转小写
$filename = strtolower($filename);
$file = __DIR__ . DIRECTORY_SEPARATOR . $filename . '.php';
if (!is_file($file)) {
die($file . ' 文件不存在');
}
$className = 'IYUU\\Rss\\' . $filename;
if (class_exists($className)) {
echo $filename . " RSS解码类正在实例化" . PHP_EOL;
return new $className();
} else {
die($filename . ' RSS解码类不存在');
}
return $item;
}
/**
* 解析命令行参数 【静态方法】
* @param string $uuid 任务标识
* @return string 类文件名
*/
private static function getCliInput($uuid)
{
self::$conf = domainRss::parser($uuid);
if (empty(self::$conf)) {
die('当前任务不存在或者未开启。' . PHP_EOL);
}
if (empty(self::$conf['site'])) {
die('解析计划任务失败:用户未配置的站点。' . PHP_EOL);
}
if (empty(self::$conf['sites'])) {
die('解析计划任务失败:用户配置的站点,当前不受支持。' . PHP_EOL);
}
if (empty(self::$conf['clients'])) {
die('解析计划任务失败当前下载器可能已经删除请编辑RSS下载任务重选下载器。' . PHP_EOL);
}
echo microtime(true) . ' 命令行参数解析完成!' . PHP_EOL;
//cli(self::$conf);
$siteName = self::$conf['site']['name'];
return static::getFileName($siteName);
}
/**
* 从站点名解析出类名(文件名)
* @param string $site_name
* @return string 类文件名
*/
public static function getFileName(string $site_name): string
{
return isset(self::SITENAME_TO_FILENAME_MAP[$site_name]) ? self::SITENAME_TO_FILENAME_MAP[$site_name] : $site_name;
}
/**
* 从类名解析出站点名(配置里站点的键名)
* @param string $class_name
* @return string
*/
public static function getSiteName(string $class_name): string
{
$classname_to_sitename_map = array_flip(static::SITENAME_TO_FILENAME_MAP);
if (array_key_exists($class_name, $classname_to_sitename_map)) {
$siteName = $classname_to_sitename_map[$class_name];
} else {
$siteName = $class_name;
}
return $siteName;
}
/**
* 获取配置
* @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;
}
/**
* 公共方法实现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] => 匿名
* )
*/
abstract public function decode($html = '');
/**
* NexusPHP通用RSS解码子类可以重写此方法
* @param string $html
@ -231,7 +362,7 @@ abstract class AbstractRss
$torrent['title'] = '';
$torrent['details'] = $details;
$torrent['download'] = $link;
$torrent['filename'] = $id.'.torrent';
$torrent['filename'] = $id . '.torrent';
$torrent['type'] = 0; // 免费0
$torrent['time'] = date("Y-m-d H:i:s", $time);
$torrent['size'] = dataSize($length);
@ -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';
}
/**
* 公共方法实现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;
$node = $item->getElementsByTagName('description')->item(0);
if ($node != null) {
$item->removeChild($node);
}
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;
return $item;
}
/**
* 回调函数,子类可以重写此方法
* @param string $html
*/
public function checkCallback($html = '')
{
if (strpos((string)$html, 'invalid passkey') !== false) {
die('passkey填写错误请重新填写');
}
if (is_null($html)) {
exit(1);
}
}
/**
* 获取配置
* @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 = '');
}

View File

@ -2,6 +2,7 @@
/**
* beitai RSS解码类
*/
namespace IYUU\Rss;
class beitai extends AbstractRss
@ -15,12 +16,12 @@ class beitai extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* btschool RSS解码类
*/
namespace IYUU\Rss;
class btschool extends AbstractRss
@ -15,12 +16,12 @@ class btschool extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* chdbits RSS解码类
*/
namespace IYUU\Rss;
class chdbits extends AbstractRss
@ -15,12 +16,12 @@ class chdbits extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* discfan RSS解码类
*/
namespace IYUU\Rss;
class discfan extends AbstractRss
@ -15,12 +16,12 @@ class discfan extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* dmhy RSS解码类
*/
namespace IYUU\Rss;
class dmhy extends AbstractRss
@ -15,12 +16,12 @@ class dmhy extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* beitai RSS解码类
*/
namespace IYUU\Rss;
class dragonhd extends AbstractRss
@ -15,12 +16,12 @@ class dragonhd extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* eastgame RSS解码类
*/
namespace IYUU\Rss;
class eastgame extends AbstractRss
@ -15,12 +16,12 @@ class eastgame extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* chdbits RSS解码类
*/
namespace IYUU\Rss;
class haidan extends AbstractRss
@ -15,12 +16,12 @@ class haidan extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* hd4fans RSS解码类
*/
namespace IYUU\Rss;
class hd4fans extends AbstractRss
@ -15,12 +16,12 @@ class hd4fans extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* hdai RSS解码类
*/
namespace IYUU\Rss;
class hdai extends AbstractRss
@ -15,12 +16,12 @@ class hdai extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* hdarea RSS解码类
*/
namespace IYUU\Rss;
class hdarea extends AbstractRss
@ -15,12 +16,12 @@ class hdarea extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* hdatmos RSS解码类
*/
namespace IYUU\Rss;
class hdatmos extends AbstractRss
@ -15,12 +16,12 @@ class hdatmos extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -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页面
@ -34,7 +36,7 @@ class hdbits extends AbstractRss
$url = $this->rss_page;
}
$url = str_replace("{}", $this->passkey, $url);
echo $this->site." 正在请求RSS... {$url}". PHP_EOL;
echo $this->site . " 正在请求RSS... {$url}" . PHP_EOL;
$res = $this->curl->get($this->host . $url);
if ($res->http_status_code == 200) {
if (strpos((string)$res->response, 'Authentication failed') !== false) {
@ -57,7 +59,7 @@ class hdbits extends AbstractRss
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
try {
$items = [];
$xml = new DOMDocument();
@ -75,7 +77,7 @@ class hdbits extends AbstractRss
$torrent['title'] = '';
$torrent['details'] = $details;
$torrent['download'] = $link;
$torrent['filename'] = $id.'.torrent';
$torrent['filename'] = $id . '.torrent';
$torrent['type'] = 0; // 免费0
$torrent['time'] = date("Y-m-d H:i:s", $time);
$torrent['guid'] = $guid;

View File

@ -2,6 +2,7 @@
/**
* hdchina RSS解码类
*/
namespace IYUU\Rss;
class hdchina extends AbstractRss
@ -15,12 +16,12 @@ class hdchina extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* hdcity RSS解码类
*/
namespace IYUU\Rss;
use Curl\Curl;
@ -24,12 +25,12 @@ class hdcity extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* hddolby RSS解码类
*/
namespace IYUU\Rss;
class hddolby extends AbstractRss
@ -21,18 +22,19 @@ class hddolby extends AbstractRss
$config = static::$conf['site'];
$this->passkey = isset($config['downHash']) && $config['downHash'] ? $config['downHash'] : '';
if (empty($this->passkey)) {
die($this->site.' 没有配置密钥,初始化错误。'.PHP_EOL);
die($this->site . ' 没有配置密钥,初始化错误。' . PHP_EOL);
}
}
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* hdfans RSS解码类
*/
namespace IYUU\Rss;
class hdfans extends AbstractRss
@ -15,12 +16,12 @@ class hdfans extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -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');
/**
* 初始化 第二步
*/
@ -23,18 +23,19 @@ class hdhome extends AbstractRss
$config = static::$conf['site'];
$this->passkey = isset($config['downHash']) && $config['downHash'] ? $config['downHash'] : '';
if (empty($this->passkey)) {
die($this->site.' 没有配置密钥,初始化错误。'.PHP_EOL);
die($this->site . ' 没有配置密钥,初始化错误。' . PHP_EOL);
}
}
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace IYUU\Rss;
use DOMDocument;
@ -34,7 +35,7 @@ class hdpost extends AbstractRss
/**
* 抽象方法,在类中实现
* 请求url获取html页面
* @param string $url
* @param string $url
* @return string
*/
public function get($url = '')
@ -48,7 +49,7 @@ class hdpost extends AbstractRss
// 2. 替换
$url = str_replace("{rsskey}", static::getConfig('site.rsskey', ''), $url);
echo $this->site." 正在请求RSS... {$url}". PHP_EOL;
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);
if ($res->http_status_code == 200) {
@ -62,12 +63,12 @@ class hdpost extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,27 +2,27 @@
/**
* 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为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* hdtime RSS解码类
*/
namespace IYUU\Rss;
class hdtime extends AbstractRss
@ -15,12 +16,12 @@ class hdtime extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace IYUU\Rss;
use DOMDocument;
@ -14,12 +15,12 @@ class hdtorrents extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
try {
$items = [];
$xml = new DOMDocument();
@ -39,7 +40,7 @@ class hdtorrents extends AbstractRss
$torrent['title'] = '';
$torrent['details'] = '';
$torrent['download'] = $link;
$torrent['filename'] = $id.'.torrent';
$torrent['filename'] = $id . '.torrent';
$torrent['type'] = 0; // 免费0
$torrent['time'] = date("Y-m-d H:i:s", $time);
$torrent['guid'] = $guid;

View File

@ -2,6 +2,7 @@
/**
* hdzone RSS解码类
*/
namespace IYUU\Rss;
class hdzone extends AbstractRss
@ -15,12 +16,12 @@ class hdzone extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* hitpt RSS解码类
*/
namespace IYUU\Rss;
class hitpt extends AbstractRss
@ -15,12 +16,12 @@ class hitpt extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* joyhd RSS解码类
*/
namespace IYUU\Rss;
class joyhd extends AbstractRss
@ -15,12 +16,12 @@ class joyhd extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* keepfrds RSS解码类
*/
namespace IYUU\Rss;
class keepfrds extends AbstractRss
@ -15,12 +16,12 @@ class keepfrds extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* leaguehd RSS解码类
*/
namespace IYUU\Rss;
class leaguehd extends AbstractRss
@ -15,12 +16,12 @@ class leaguehd extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* mteam RSS解码类
*/
namespace IYUU\Rss;
class mteam extends AbstractRss
@ -19,12 +20,12 @@ class mteam extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* nanyangpt RSS解码类
*/
namespace IYUU\Rss;
class nanyangpt extends AbstractRss
@ -15,12 +16,12 @@ class nanyangpt extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* nicept RSS解码类
*/
namespace IYUU\Rss;
class nicept extends AbstractRss
@ -15,12 +16,12 @@ class nicept extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* npupt RSS解码类
*/
namespace IYUU\Rss;
class npupt extends AbstractRss
@ -15,12 +16,12 @@ class npupt extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* opencd RSS解码类
*/
namespace IYUU\Rss;
class opencd extends AbstractRss
@ -15,12 +16,12 @@ class opencd extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

View File

@ -2,6 +2,7 @@
/**
* oshen RSS解码类
*/
namespace IYUU\Rss;
class oshen extends AbstractRss
@ -15,12 +16,12 @@ class oshen extends AbstractRss
/**
* 抽象方法,在类中实现
* 解码html为种子数组
* @param string $html
* @param string $html
* @return array
*/
public function decode($html = '')
{
echo "正在解码RSS资源...". PHP_EOL;
echo "正在解码RSS资源..." . PHP_EOL;
return $this->NexusPHP($html);
}
}

Some files were not shown because too many files have changed in this diff Show More