From 69521a1f1f1bae77dc6da867f535a1a99d2d1a6e Mon Sep 17 00:00:00 2001 From: jerry Date: Wed, 24 Feb 2021 23:37:00 +0800 Subject: [PATCH] cleanup code, update some features add Hitokoto API add Closure for access_token add working_dir() global function adjust reply() method to .handle_quick_operation --- docs/component/data-provider.md | 37 +++++++++++++++++++++++++++++ docs/component/global-functions.md | 27 +++++++++++++++++++++ mkdocs.yml | 5 ++-- src/Module/Example/Hello.php | 15 +++++++++++- src/ZM/ConsoleApplication.php | 7 +----- src/ZM/Context/Context.php | 18 +++++++------- src/ZM/Event/ServerEventHandler.php | 13 +++++++--- src/ZM/global_functions.php | 9 ++++++- 8 files changed, 109 insertions(+), 22 deletions(-) create mode 100644 docs/component/data-provider.md diff --git a/docs/component/data-provider.md b/docs/component/data-provider.md new file mode 100644 index 00000000..5bf8c7c3 --- /dev/null +++ b/docs/component/data-provider.md @@ -0,0 +1,37 @@ +# 存储管理(文件) + +DataProvider 是框架内提供的一个简易的文件管理类。 + +定义:`\ZM\Utils\DataProvider` + +## DataProvider::getWorkingDir() + +同 `working_dir()`。 + +## DataProvider::getFrameworkLink() + +同 `ZMConfig::get("global", "http_reverse_link")`,获取反向代理的链接。 + +## DataProvider::getDataFolder() + +获取配置项 `zm_data` 指定的目录。 + +## DataProvider::saveToJson() + +将变量内容保存为 json 格式的文件,存储在 `zm_data/config/` 目录下或子目录下。 + +定义:`saveToJson($filename, $file_array)` + +`$filename` 是文件名,不需要加后缀,比如你想保存成 `foo/bar.json`,这里写 `foo/bar` 就好。如果不想要二级目录,就直接写 `bar`,不需要加 `.json` 后缀。 + +这里只支持二级目录,不支持更多级的子目录。 + +`$file_array` 为内容,一般是数组,比如你缓存了一个 API 接口返回的数据,然后直接解析成数组后丢给它就好了。 + +## DataProvider::loadFromJson() + +从 json 文件加载内容至变量。 + +定义:`loadFromJson($filename)` + +文件名同上 `saveToJson()` 的定义,解析后的返回值为原先的内容或 `null`(如果文件不存在或 json 解析失败)。 \ No newline at end of file diff --git a/docs/component/global-functions.md b/docs/component/global-functions.md index 7b9bfbeb..f4e6e37e 100644 --- a/docs/component/global-functions.md +++ b/docs/component/global-functions.md @@ -227,5 +227,32 @@ bot()->sendPrivateMsg(123456, "你好啊!!"); // 等同于 ZMRobot::getRandom()->sendPrivateMsg(123456, "你好啊!!"); ``` +## zm_atomic() +获取计时器,效果同 `\ZM\Store\ZMAtomic::get($name)`。 +定义:`zm_atmoic($name)` + +## uuidgen() + +> 2.2.5 版本起可用。 + +生成一个随机的 uuid,支持大写或小写。 + +定义:`uuidgen($uppercase = false)` + +当 `$uppercase` 为 `true` 时,返回的 uuid 中字母都是大写。 + +## working_dir() + +> 2.2.6 版本起可用。 + +获取框架运行的工作目录。例如你是从 `/root/framework-starter/` 目录启动的框架,`vendor/bin/start server`,那么 `working_dir()` 返回的就是 `/root/framework-starter`。(注意,返回的目录最后没有斜杠,请自行添加。) + +## getAllFdByConnectType() + +获取同类型的所有连接的描述符 ID。 + +定义:`getAllFdByConnectType(string $type = 'default'): array` + +当 `$type` 为 `qq` 时,则返回所有 OneBot 机器人接入的 WebSocket 连接号。 \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 1d4a0f03..111e8c41 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -10,8 +10,8 @@ theme: favicon: assets/favicon.png language: zh palette: - primary: red - accent: red + primary: indigo + accent: indigo features: - navigation.tabs extra_javascript: @@ -81,6 +81,7 @@ nav: - Redis 数据库: component/redis.md - ZMAtomic 原子计数器: component/atomics.md - SpinLock 自旋锁: component/spin-lock.md + - 文件管理: component/data-provider.md - 协程池: component/coroutine-pool.md - 单例类: component/singleton-trait.md - ZMUtil 杂项: component/zmutil.md diff --git a/src/Module/Example/Hello.php b/src/Module/Example/Hello.php index 6f6d8f6c..3e9ffd91 100644 --- a/src/Module/Example/Hello.php +++ b/src/Module/Example/Hello.php @@ -11,6 +11,7 @@ use ZM\Console\Console; use ZM\Annotation\CQ\CQCommand; use ZM\Annotation\Http\RequestMapping; use ZM\Event\EventDispatcher; +use ZM\Requests\ZMRequest; use ZM\Utils\ZMUtil; /** @@ -45,6 +46,18 @@ class Hello return "你好啊,我是由炸毛框架构建的机器人!"; } + /** + * 一个最基本的第三方 API 接口使用示例 + * @CQCommand("一言") + */ + public function hitokoto() { + $api_result = ZMRequest::get("https://v1.hitokoto.cn/"); + if ($api_result === false) return "接口请求出错,请稍后再试!"; + $obj = json_decode($api_result, true); + if ($obj === null) return "接口解析出错!可能返回了非法数据!"; + return $obj["hitokoto"] . "\n----「" . $obj["from"] . "」"; + } + /** * 一个简单随机数的功能demo * 问法1:随机数 1 20 @@ -89,7 +102,7 @@ class Hello * @return string */ public function paramGet($param) { - return "Hello, ".$param["name"]; + return "Hello, " . $param["name"]; } /** diff --git a/src/ZM/ConsoleApplication.php b/src/ZM/ConsoleApplication.php index e190d9ff..36a0e6b2 100644 --- a/src/ZM/ConsoleApplication.php +++ b/src/ZM/ConsoleApplication.php @@ -99,12 +99,7 @@ class ConsoleApplication extends Application private function selfCheck() { if (!extension_loaded("swoole")) die("Can not find swoole extension.\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/19"); 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 (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"); + if (version_compare(PHP_VERSION, "7.2") == -1) die("PHP >= 7.2 required."); return true; } } diff --git a/src/ZM/Context/Context.php b/src/ZM/Context/Context.php index c8900e26..9ead9f13 100644 --- a/src/ZM/Context/Context.php +++ b/src/ZM/Context/Context.php @@ -12,6 +12,7 @@ use swoole_server; use ZM\ConnectionManager\ConnectionObject; use ZM\ConnectionManager\ManagerGM; use ZM\Console\Console; +use ZM\Event\EventDispatcher; use ZM\Exception\InvalidArgumentException; use ZM\Exception\WaitTimeoutException; use ZM\Http\Response; @@ -112,21 +113,20 @@ class Context implements ContextInterface $this->setCache("has_reply", true); $data = $this->getData(); $conn = $this->getConnection(); - switch ($data["message_type"]) { - case "group": - return (new ZMRobot($conn))->setCallback($yield)->sendGroupMsg($data["group_id"], $msg); - case "private": - return (new ZMRobot($conn))->setCallback($yield)->sendPrivateMsg($data["user_id"], $msg); - } - return null; + return (new ZMRobot($conn))->setCallback($yield)->callExtendedAPI(".handle_quick_operation", [ + "context" => $data, + "operation" => [ + "reply" => $msg + ] + ]); } return false; } public function finalReply($msg, $yield = false) { self::$context[$this->cid]["cache"]["block_continue"] = true; - if ($msg == "") return true; - return $this->reply($msg, $yield); + if ($msg != "") $this->reply($msg, $yield); + EventDispatcher::interrupt(); } /** diff --git a/src/ZM/Event/ServerEventHandler.php b/src/ZM/Event/ServerEventHandler.php index 0375d56c..174af856 100644 --- a/src/ZM/Event/ServerEventHandler.php +++ b/src/ZM/Event/ServerEventHandler.php @@ -6,6 +6,7 @@ namespace ZM\Event; +use Closure; use Co; use Error; use Exception; @@ -410,9 +411,15 @@ class ServerEventHandler Console::debug("Calling Swoole \"open\" event from fd=" . $request->fd); unset(Context::$context[Co::getCid()]); $type = strtolower($request->header["x-client-role"] ?? $request->get["type"] ?? ""); - $access_token = explode(" ", $request->header["authorization"] ?? $request->get["token"] ?? "")[1] ?? ""; - if (($a = ZMConfig::get("global", "access_token")) != "") { - if ($access_token !== $a) { + $access_token = explode(" ", $request->header["authorization"] ?? "")[1] ?? $request->get["token"] ?? ""; + $token = ZMConfig::get("global", "access_token"); + if ($token instanceof Closure) { + if (!$token($access_token)) { + $server->close($request->fd); + Console::warning("Unauthorized access_token: " . $access_token); + } + } elseif (is_string($token)) { + if ($access_token !== $token) { $server->close($request->fd); Console::warning("Unauthorized access_token: " . $access_token); return; diff --git a/src/ZM/global_functions.php b/src/ZM/global_functions.php index 3a18d339..df61744e 100644 --- a/src/ZM/global_functions.php +++ b/src/ZM/global_functions.php @@ -329,4 +329,11 @@ function uuidgen($uppercase = false) { $data[8] = chr(ord($data[8]) & 0x3f | 0x80); return $uppercase ? strtoupper(vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4))) : vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); -} \ No newline at end of file +} + +function working_dir() { + if (LOAD_MODE == 0) return WORKING_DIR; + elseif (LOAD_MODE == 1) return LOAD_MODE_COMPOSER_PATH; + elseif (LOAD_MODE == 2) return realpath('.'); + return null; +}