mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-03 23:05:37 +08:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc31a1654d | ||
|
|
dfca486b64 | ||
|
|
754c2846fe | ||
|
|
eed670cb50 | ||
|
|
9e824d960f | ||
|
|
992b6020a5 | ||
|
|
d51dbef437 | ||
|
|
7f058638bd | ||
|
|
c04130fed1 | ||
|
|
7fefcb850a | ||
|
|
1fe54d4b94 | ||
|
|
13a32bec79 | ||
|
|
0f5786c8c4 | ||
|
|
4ed046769f | ||
|
|
690980f72d | ||
|
|
f025eeb34a | ||
|
|
d642f50ef1 | ||
|
|
2900754307 | ||
|
|
dffeac668d | ||
|
|
b6756179f5 | ||
|
|
1adcf76203 | ||
|
|
5b003ab575 | ||
|
|
75f6aa531e | ||
|
|
6e1f4820f8 | ||
|
|
50ce81334b | ||
|
|
0ed0aa089a | ||
|
|
102ba769ec | ||
|
|
e062f484b1 | ||
|
|
3be3e8412a | ||
|
|
ab5abf1c00 | ||
|
|
3aaa72cfb9 | ||
|
|
10f846c214 | ||
|
|
67a42c4be9 | ||
|
|
7e4e58a322 | ||
|
|
5de283d30c | ||
|
|
7513fd1a1d |
39
README.md
39
README.md
@@ -1,33 +1,45 @@
|
||||
# zhamao-framework
|
||||
<div align="center">
|
||||
<img src="/resources/images/logo_trans.png" height = "150" alt="炸毛框架"><br>
|
||||
<h2>炸毛框架</h2>
|
||||
炸毛框架 (zhamao-frameowork) 是一个协程高性能的聊天机器人 + Web 服务器开发框架<br><br>
|
||||
|
||||
[]()
|
||||
[](https://github.com/zhamao-robot/zhamao-framework/blob/master/LICENSE)
|
||||
[](https://packagist.org/packages/zhamao/framework)
|
||||
[]()
|
||||
[]()
|
||||
|
||||
[](https://github.com/zhamao-robot/zhamao-framework/search?q=stupid)
|
||||
[](https://github.com/zhamao-robot/zhamao-framework/search?q=TODO)
|
||||
|
||||
协程高性能的 **QQ 机器人 + Web 服务器** 开发框架(炸毛框架)。
|
||||
</div>
|
||||
|
||||
<img src="https://avatars0.githubusercontent.com/u/48620312" height = "200" alt="炸毛框架" align=center/>
|
||||
## 开发者注意
|
||||
**v2.0 版本已经开始公测了,但是文档还在光速编写中,可以现行进行测试!**
|
||||
|
||||
**炸毛框架目前经过实验可以直接在 PHP8 环境上运行,但是细节部分未经充分测试,如果在 PHP8 环境下运行出现问题,请及时提出 Issue,谢谢!**
|
||||
|
||||
**由于 CQHTTP 不再提供维护,转为 [OneBot 标准](https://github.com/howmanybots/onebot)(原 CQHTTP 插件衍生而来的机器人 HTTP 接口标准),本框架也将在未来改为兼容此标准。**
|
||||
|
||||
**以上涉及的变更将在下一个大版本 (v2.0.0) 更新,请关注 2.0-dev 分支 和 Project 模块!**
|
||||
|
||||
**v2.0版本即将到来,请持续关注 [新文档](https://docs-v2.zhamao.xin/) 进度和 Project 模块展示的测试进度!**
|
||||
|
||||
## 简介
|
||||
zhamao-framework 是一个基于 酷Q 的 PHP Swoole 的机器人框架,它会对 QQ 机器人收到的消息进行解析处理,并以模块化的形式进行开发,来完成机器人的自然语言对话等功能。
|
||||
|
||||
框架对接 酷Q 的桥梁是 **CQHTTP** 插件,这里是它的[项目地址](https://github.com/richardchien/coolq-http-api/)。
|
||||
zhamao-framework 是一个 PHP Swoole 的聊天机器人框架,兼容 OneBot 标准,它会对微信公众号等终端收到的消息进行解析处理,并以模块化的形式进行开发,来完成机器人的自然语言对话等功能。
|
||||
|
||||
除了起到解析消息的作用,炸毛框架 还提供了完整的 WebSocket + HTTP 服务器,你还能用此框架构建出高性能的 API 接口服务器。
|
||||
|
||||
## 开始
|
||||
先安装环境,环境安装见下方文档。
|
||||
1. `composer create-project zhamao/framework-starter` 从模板新建基础文档结构进行使用
|
||||
2. 你也可以直接到 **Release** 中下载最新的 phar 包,放入文件夹后 `php server.phar` 快速启动框架
|
||||
2. 你也可以直接拉取本项目,进入文件夹后 `composer update` 加载依赖后使用 `bin/start init` 快速初始化框架文件
|
||||
3. 还可以使用 Dockerfile 构建 Docker 容器
|
||||
|
||||
## 文档
|
||||
Pages托管:[https://framework.zhamao.xin/](https://framework.zhamao.xin/)
|
||||
## 文档 (v1.x)
|
||||
国内服务器:[https://docs-v1.zhamao.xin/](https://docs-v1.zhamao.xin/)
|
||||
|
||||
国内服务器:[https://framework2.zhamao.xin/](https://framework2.zhamao.xin/)
|
||||
GitHub Pages:[https://docs-v1.zhamao.me/](https://docs-v1.zhamao.me/)
|
||||
|
||||
## 特点
|
||||
- 支持多账号
|
||||
@@ -45,7 +57,6 @@ Pages托管:[https://framework.zhamao.xin/](https://framework.zhamao.xin/)
|
||||
|
||||
| 模块名称 | 说明 | 模块地址 |
|
||||
| ------------------ | -------------------------------- | ------------------------------------------------------------ |
|
||||
| 微信公众号兼容模块 | 为框架提供微信公众号订阅号兼容层 | [zhamao-wechat-patch](https://github.com/zhamao-robot/zhamao-wechat-patch) |
|
||||
| 通用模块 | 图片上传和下载模块 | [zhamao-general-tools](https://github.com/zhamao-robot/zhamao-general-tools) |
|
||||
|
||||
## 计划开发内容
|
||||
@@ -79,11 +90,15 @@ Pages托管:[https://framework.zhamao.xin/](https://framework.zhamao.xin/)
|
||||
### 支付宝
|
||||

|
||||
|
||||
如果你对我们的周边感兴趣,我们还有炸毛机器人定制 logo 的雨伞,详情咨询作者 QQ,我们会作为您捐助了本项目!
|
||||
|
||||
## 关于
|
||||
框架和 SDK 是 炸毛机器人 项目的核心框架开源部分。炸毛机器人(3276124472)是作者写的一个高性能机器人,曾获全国计算机设计大赛一等奖。
|
||||
框架和 SDK 是 炸毛机器人 项目的核心框架开源部分。炸毛机器人是作者写的一个高性能机器人,曾获全国计算机设计大赛一等奖。
|
||||
|
||||
欢迎随时在 HTTP-API 插件群里提问,当然更好的话可以加作者 QQ(627577391)或提交 Issue 进行疑难解答。
|
||||
|
||||
本项目在更新内容时,请及时关注 GitHub 动态,更新前请将自己的模块代码做好备份。
|
||||
|
||||
项目框架采用 Apache-2.0 协议开源,在分发或重写修改等操作时需遵守协议。项目模块部分(`Module` 文件夹) 在非借鉴框架内代码时可不遵守 Apache-2.0 协议进行分发和修改(声明版权)。
|
||||
|
||||
**注意**:在你使用 mirai 等 `AGPL-3.0` 协议的机器人软件与框架连接时,使用本框架需要将你编写或修改的部分使用 `AGPL-3.0` 协议重新分发。
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 1.2.x | :white_check_mark: |
|
||||
| 1.1.x | :x: |
|
||||
| 1.0.x | :x: |
|
||||
| 2.0 | :white_check_mark: |
|
||||
| 1.6.x | :white_check_mark: |
|
||||
| 1.x | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "High performance QQ robot and web server development framework",
|
||||
"minimum-stability": "stable",
|
||||
"license": "Apache-2.0",
|
||||
"version": "1.6",
|
||||
"version": "1.6.5",
|
||||
"authors": [
|
||||
{
|
||||
"name": "whale",
|
||||
@@ -21,21 +21,17 @@
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"swoole/ide-helper": "@dev",
|
||||
"ext-mbstring": "*",
|
||||
"swlib/saber": "^1.0",
|
||||
"doctrine/annotations": "~1.10",
|
||||
"ext-json": "*",
|
||||
"ext-posix": "*",
|
||||
"ext-ctype": "*",
|
||||
"ext-pdo": "*",
|
||||
"psy/psysh": "@stable"
|
||||
"psy/psysh": "@stable",
|
||||
"symfony/polyfill-ctype": "^1.20",
|
||||
"symfony/polyfill-mbstring": "^1.20"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Custom\\": "src/Custom",
|
||||
"Framework\\": "src/Framework",
|
||||
"ZM\\": "src/ZM",
|
||||
"Module\\": "src/Module"
|
||||
"ZM\\": "src/ZM"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,23 +8,23 @@ $config['host'] = '0.0.0.0';
|
||||
$config['port'] = 20001;
|
||||
|
||||
/** 框架开到公网或外部的HTTP访问链接,通过 DataProvider::getFrameworkLink() 获取 */
|
||||
$config['http_reverse_link'] = "http://127.0.0.1:".$config['port'];
|
||||
$config['http_reverse_link'] = "http://127.0.0.1:" . $config['port'];
|
||||
|
||||
/** 框架是否启动debug模式 */
|
||||
$config['debug_mode'] = false;
|
||||
|
||||
/** 存放框架内文件数据的目录 */
|
||||
$config['zm_data'] = realpath(__DIR__ . "/../").'/zm_data/';
|
||||
$config['zm_data'] = realpath(__DIR__ . "/../") . '/zm_data/';
|
||||
|
||||
/** 存放各个模块配置文件的目录 */
|
||||
$config['config_dir'] = $config['zm_data'].'config/';
|
||||
$config['config_dir'] = $config['zm_data'] . 'config/';
|
||||
|
||||
/** 存放崩溃和运行日志的目录 */
|
||||
$config['crash_dir'] = $config['zm_data'].'crash/';
|
||||
$config['crash_dir'] = $config['zm_data'] . 'crash/';
|
||||
|
||||
/** 对应swoole的server->set参数 */
|
||||
$config['swoole'] = [
|
||||
'log_file' => $config['crash_dir'].'swoole_error.log',
|
||||
'log_file' => $config['crash_dir'] . 'swoole_error.log',
|
||||
'worker_num' => 1,
|
||||
'dispatch_mode' => 2,
|
||||
//'task_worker_num' => 1,
|
||||
@@ -88,7 +88,7 @@ $config['static_file_server'] = [
|
||||
|
||||
/** 注册 Swoole Server 事件注解的类列表 */
|
||||
$config['server_event_handler_class'] = [
|
||||
\Framework\ServerEventHandler::class, //默认不可删除,否则会不能使用框架
|
||||
\Framework\ServerEventHandler::class,
|
||||
];
|
||||
|
||||
return $config;
|
||||
|
||||
BIN
resources/images/logo_trans.png
Normal file
BIN
resources/images/logo_trans.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
@@ -34,7 +34,8 @@ class FrameworkLoader
|
||||
/** @var Server */
|
||||
private $server;
|
||||
|
||||
public function __construct($args = []) {
|
||||
public function __construct($args = [])
|
||||
{
|
||||
$this->requireGlobalFunctions();
|
||||
if (LOAD_MODE == 0) define("WORKING_DIR", getcwd());
|
||||
elseif (LOAD_MODE == 1) define("WORKING_DIR", realpath(__DIR__ . "/../../"));
|
||||
@@ -45,6 +46,29 @@ class FrameworkLoader
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
require_once DataProvider::getWorkingDir() . "/vendor/autoload.php";
|
||||
}
|
||||
if (LOAD_MODE == 0) {
|
||||
echo "* This is repository mode.\n";
|
||||
$composer = json_decode(file_get_contents(DataProvider::getWorkingDir() . "/composer.json"), true);
|
||||
if (!isset($composer["autoload"]["psr-4"]["Module\\"])) {
|
||||
echo "框架源码模式需要在autoload文件中添加Module目录为自动加载,是否添加?[Y/n] ";
|
||||
$r = strtolower(trim(fgets(STDIN)));
|
||||
if ($r === "" || $r === "y") {
|
||||
$composer["autoload"]["psr-4"]["Module\\"] = "src/Module";
|
||||
$composer["autoload"]["psr-4"]["Custom\\"] = "src/Custom";
|
||||
$r = file_put_contents(DataProvider::getWorkingDir() . "/composer.json", json_encode($composer, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
|
||||
if ($r !== false) {
|
||||
echo "成功添加!请重新进行 composer update !\n";
|
||||
exit(1);
|
||||
} else {
|
||||
echo "添加失败!请按任意键继续!";
|
||||
fgets(STDIN);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (LOAD_MODE == 2) {
|
||||
require_once FRAMEWORK_DIR . "/vendor/autoload.php";
|
||||
spl_autoload_register('phar_classloader');
|
||||
@@ -76,7 +100,10 @@ class FrameworkLoader
|
||||
self::$argv[] = "--disable-console-input";
|
||||
}
|
||||
$this->server->set($settings);
|
||||
$all_event_class = self::$settings->get("server_event_handler_class");
|
||||
$all_event_class = self::$settings->get("server_event_handler_class") ?? [];
|
||||
if (!in_array(ServerEventHandler::class, $all_event_class)) {
|
||||
$all_event_class[] = ServerEventHandler::class;
|
||||
}
|
||||
$event_list = [];
|
||||
foreach ($all_event_class as $v) {
|
||||
$reader = new AnnotationReader();
|
||||
@@ -125,15 +152,6 @@ class FrameworkLoader
|
||||
}
|
||||
if (in_array("--debug-mode", self::$argv))
|
||||
Console::warning("You are in debug mode, do not use in production!");
|
||||
register_shutdown_function(function() {
|
||||
$error = error_get_last();
|
||||
if(isset($error["type"]) && $error["type"] == 1) {
|
||||
if(mb_strpos($error["message"], "require") !== false && mb_strpos($error["message"], "callback") !== false) {
|
||||
echo "\e[38;5;203mYou may need to update your \"global.php\" config!\n";
|
||||
echo "Please see: https://github.com/zhamao-robot/zhamao-framework/issues/15\e[m\n";
|
||||
}
|
||||
}
|
||||
});
|
||||
$this->server->start();
|
||||
} catch (Exception $e) {
|
||||
Console::error("Framework初始化出现错误,请检查!");
|
||||
@@ -142,11 +160,13 @@ class FrameworkLoader
|
||||
}
|
||||
}
|
||||
|
||||
private function requireGlobalFunctions() {
|
||||
private function requireGlobalFunctions()
|
||||
{
|
||||
require_once __DIR__ . '/global_functions.php';
|
||||
}
|
||||
|
||||
private function defineProperties() {
|
||||
private function defineProperties()
|
||||
{
|
||||
define("ZM_START_TIME", microtime(true));
|
||||
define("ZM_DATA", self::$settings->get("zm_data"));
|
||||
define("ZM_VERSION", json_decode(file_get_contents(__DIR__ . "/../../composer.json"), true)["version"] ?? "unknown");
|
||||
@@ -164,20 +184,20 @@ class FrameworkLoader
|
||||
define("ZM_DEFAULT_FETCH_MODE", self::$settings->get("sql_config")["sql_default_fetch_mode"] ?? 4);
|
||||
}
|
||||
|
||||
private function selfCheck() {
|
||||
private function selfCheck()
|
||||
{
|
||||
if (!extension_loaded("swoole")) die("Can not find swoole extension.\n");
|
||||
if (version_compare(SWOOLE_VERSION, "4.4.13") == -1) die("You must install swoole version >= 4.4.13 !");
|
||||
//if (!extension_loaded("gd")) die("Can not find gd extension.\n");
|
||||
if (!extension_loaded("sockets")) die("Can not find sockets extension.\n");
|
||||
if (!extension_loaded("ctype")) die("Can not find ctype extension.\n");
|
||||
//if (!extension_loaded("sockets")) die("Can not find sockets extension.\n");
|
||||
if (!function_exists("ctype_alpha")) die("Can not find ctype extension.\n");
|
||||
if (!function_exists("mb_substr")) die("Can not find mbstring extension.\n");
|
||||
if (substr(PHP_VERSION, 0, 1) != "7") die("PHP >=7 required.\n");
|
||||
if (substr(PHP_VERSION, 0, 1) < "7") die("PHP >=7 required.\n");
|
||||
//if (!function_exists("curl_exec")) die("Can not find curl extension.\n");
|
||||
//if (!class_exists("ZipArchive")) die("Can not find Zip extension.\n");
|
||||
//if (!file_exists(CRASH_DIR . "last_error.log")) die("Can not find log file.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
global $motd;
|
||||
|
||||
@@ -27,7 +27,8 @@ class RequestEvent implements SwooleEvent
|
||||
*/
|
||||
private $response;
|
||||
|
||||
public function __construct(Request $request, Response $response) {
|
||||
public function __construct(Request $request, Response $response)
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->response = $response;
|
||||
}
|
||||
@@ -36,7 +37,8 @@ class RequestEvent implements SwooleEvent
|
||||
* @return $this|SwooleEvent
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onActivate() {
|
||||
public function onActivate()
|
||||
{
|
||||
ZMUtil::checkWait();
|
||||
foreach (ZMBuf::globals("http_header") as $k => $v) {
|
||||
$this->response->setHeader($k, $v);
|
||||
@@ -49,7 +51,10 @@ class RequestEvent implements SwooleEvent
|
||||
$params = [];
|
||||
while (true) {
|
||||
$r = array_shift($uri);
|
||||
if ($r === null) break;
|
||||
if ($r === null) {
|
||||
if ($node == ZMBuf::$req_mapping) goto statics;
|
||||
else break;
|
||||
}
|
||||
if (($cnt = count($node["son"] ?? [])) == 1) {
|
||||
if (isset($node["param_route"])) {
|
||||
foreach ($node["son"] as $k => $v) {
|
||||
@@ -80,13 +85,18 @@ class RequestEvent implements SwooleEvent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
statics:
|
||||
if (ZMBuf::globals("static_file_server")["status"]) {
|
||||
$base_dir = ZMBuf::globals("static_file_server")["document_root"];
|
||||
$base_index = ZMBuf::globals("static_file_server")["document_index"];
|
||||
$uri = $this->request->server["request_uri"];
|
||||
$path = realpath($base_dir . urldecode($uri));
|
||||
if ($path !== false) {
|
||||
if (is_dir($path) && mb_substr($uri, -1, 1) != "/") {
|
||||
$this->response->redirect($uri . "/", 301);
|
||||
$this->response->end();
|
||||
return $this;
|
||||
}
|
||||
if (is_dir($path)) $path = $path . '/';
|
||||
$work = realpath(DataProvider::getWorkingDir()) . '/';
|
||||
if (strpos($path, $work) !== 0) {
|
||||
@@ -150,7 +160,8 @@ class RequestEvent implements SwooleEvent
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function onAfter() {
|
||||
public function onAfter()
|
||||
{
|
||||
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
|
||||
if (strtolower($v->type) == "request" && $this->parseSwooleRule($v)) {
|
||||
$c = $v->class;
|
||||
@@ -162,12 +173,14 @@ class RequestEvent implements SwooleEvent
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function responseStatus(int $int) {
|
||||
private function responseStatus(int $int)
|
||||
{
|
||||
$this->response->status($int);
|
||||
$this->response->end();
|
||||
}
|
||||
|
||||
private function parseSwooleRule($v) {
|
||||
private function parseSwooleRule($v)
|
||||
{
|
||||
switch (explode(":", $v->rule)[0]) {
|
||||
case "containsGet":
|
||||
case "containsPost":
|
||||
|
||||
@@ -184,7 +184,7 @@ class Response
|
||||
* @return mixed
|
||||
*/
|
||||
public function redirect($location, $http_code = null) {
|
||||
return $this->redirect($location, $http_code);
|
||||
return $this->response->redirect($location, $http_code);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,16 +22,11 @@ class ZMRequest
|
||||
* 如果请求失败或返回状态不是200,则返回 false
|
||||
*/
|
||||
public static function get($url, $headers = [], $set = [], $return_body = true) {
|
||||
$parse = parse_url($url);
|
||||
if (!isset($parse["host"])) {
|
||||
Console::warning("ZMRequest: url must contains scheme such as \"http(s)\"");
|
||||
return false;
|
||||
}
|
||||
if(!isset($parse["path"])) $parse["path"] = "/";
|
||||
$port = $parse["port"] ?? (($parse["scheme"] ?? "http") == "https" ? 443 : 80);
|
||||
$cli = new Client($parse["host"], $port, (($parse["scheme"] ?? "http") == "https" ? true : false));
|
||||
$cli->setHeaders($headers);
|
||||
/** @var Client $cli */
|
||||
list($cli, $parse) = self::getNewClient($url);
|
||||
if($cli === null) return false;
|
||||
$cli->set($set == [] ? ['timeout' => 15.0] : $set);
|
||||
$cli->setHeaders($headers);
|
||||
$cli->get($parse["path"] . (isset($parse["query"]) ? "?" . $parse["query"] : ""));
|
||||
if ($return_body) {
|
||||
if ($cli->errCode != 0 || $cli->statusCode != 200) return false;
|
||||
@@ -56,14 +51,9 @@ class ZMRequest
|
||||
* @return bool|string|Client
|
||||
*/
|
||||
public static function post($url, array $header, $data, $set = [], $return_body = true) {
|
||||
$parse = parse_url($url);
|
||||
if (!isset($parse["host"])) {
|
||||
Console::warning("ZMRequest: url must contains scheme such as \"http(s)://\"");
|
||||
return false;
|
||||
}
|
||||
if(!isset($parse["path"])) $parse["path"] = "/";
|
||||
$port = $parse["port"] ?? (($parse["scheme"] ?? "http") == "https" ? 443 : 80);
|
||||
$cli = new Client($parse["host"], $port, (($parse["scheme"] ?? "http") == "https" ? true : false));
|
||||
/** @var Client $cli */
|
||||
list($cli, $parse) = self::getNewClient($url);
|
||||
if($cli === null) return false;
|
||||
$cli->set($set == [] ? ['timeout' => 15.0] : $set);
|
||||
$cli->setHeaders($header);
|
||||
$cli->post($parse["path"] . (isset($parse["query"]) ? ("?" . $parse["query"]) : ""), $data);
|
||||
@@ -97,15 +87,16 @@ class ZMRequest
|
||||
return Saber::session($option);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
* @param array $attribute
|
||||
* @param bool $return_body
|
||||
* @return bool|string|Client
|
||||
*/
|
||||
public static function request($url, $attribute = [], $return_body = true) {
|
||||
$parse = parse_url($url);
|
||||
if (!isset($parse["host"])) {
|
||||
Console::warning("ZMRequest: url must contains scheme such as \"http(s)://\"");
|
||||
return false;
|
||||
}
|
||||
if(!isset($parse["path"])) $parse["path"] = "/";
|
||||
$port = $parse["port"] ?? (($parse["scheme"] ?? "http") == "https" ? 443 : 80);
|
||||
$cli = new Client($parse["host"], $port, (($parse["scheme"] ?? "http") == "https" ? true : false));
|
||||
/** @var Client $cli */
|
||||
list($cli, $parse) = self::getNewClient($url);
|
||||
if($cli === null) return false;
|
||||
$cli->set($attribute["set"] ?? ["timeout" => 15.0]);
|
||||
$cli->setMethod($attribute["method"] ?? "GET");
|
||||
$cli->setHeaders($attribute["headers"] ?? []);
|
||||
@@ -126,4 +117,37 @@ class ZMRequest
|
||||
return $cli;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
* @param null|bool $dst
|
||||
* @return bool
|
||||
*/
|
||||
public static function downloadFile($url, $dst = null) {
|
||||
/** @var Client $cli */
|
||||
list($cli, $parse) = self::getNewClient($url);
|
||||
if($cli === null) return false;
|
||||
$cli->set(["timeout" => 60.0]);
|
||||
$save_path = $dst === null ? "/tmp/_zm_".mt_rand(1000000, 9999999) : $dst;
|
||||
$result = $cli->download($parse["path"] . (isset($parse["query"]) ? "?" . $parse["query"] : ""), $save_path);
|
||||
if($result === false) return false;
|
||||
elseif ($dst === null) return $save_path;
|
||||
else return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
* @return bool|array
|
||||
*/
|
||||
private static function getNewClient($url) {
|
||||
$parse = parse_url($url);
|
||||
if (!isset($parse["host"])) {
|
||||
Console::warning("ZMRequest: url must contains scheme such as \"http(s)://\"");
|
||||
return false;
|
||||
}
|
||||
if(!isset($parse["path"])) $parse["path"] = "/";
|
||||
$port = $parse["port"] ?? (($parse["scheme"] ?? "http") == "https" ? 443 : 80);
|
||||
$cli = new Client($parse["host"], $port, ($parse["scheme"] ?? "http") == "https");
|
||||
return [$cli, $parse];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user