mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-02 22:35:38 +08:00
Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d1952f5f8 | ||
|
|
6543574695 | ||
|
|
5b1c771a2d | ||
|
|
29d7d07c8e | ||
|
|
e85e1e57b1 | ||
|
|
90a4c6803e | ||
|
|
ff1b43ad89 | ||
|
|
cdd273808c | ||
|
|
f8bcc359da | ||
|
|
ccc0280d2f | ||
|
|
bd98608d2e | ||
|
|
90b6580e80 | ||
|
|
64899a50c1 | ||
|
|
d12f0bf317 | ||
|
|
422dd81bbf | ||
|
|
3a6c821249 | ||
|
|
a12b5eadf3 | ||
|
|
27c5debcb0 | ||
|
|
594b7f5f82 | ||
|
|
2c28ed9ab8 | ||
|
|
5f3a626557 | ||
|
|
1ebcfa8e7e | ||
|
|
3edab143c3 | ||
|
|
9cd5f24d2f | ||
|
|
34919afb36 | ||
|
|
6282da4972 | ||
|
|
de4748860c | ||
|
|
c7736a7c3e | ||
|
|
3f9493ae7e | ||
|
|
dbda5dc299 | ||
|
|
c9ab695a9e | ||
|
|
bb57efc149 | ||
|
|
76543d5ec0 | ||
|
|
598f568b8c | ||
|
|
fc8c0b540a | ||
|
|
af75fc2f94 | ||
|
|
b94bbbca20 | ||
|
|
784fc1697b | ||
|
|
190eba585b | ||
|
|
f97b87d5e5 | ||
|
|
2c1a158d3e | ||
|
|
90de54c6a3 | ||
|
|
d596c315f2 | ||
|
|
52afaa3fb9 | ||
|
|
47cca37854 | ||
|
|
0fa49171b9 | ||
|
|
ea1d14ba00 | ||
|
|
a01791ddbe | ||
|
|
51a9c5c4e8 | ||
|
|
b1e37943df | ||
|
|
5459d1c5ff | ||
|
|
21373097bb | ||
|
|
f4f7327695 | ||
|
|
36fc2cb4cd | ||
|
|
b7469b9dd4 |
@@ -6,67 +6,77 @@ declare(strict_types=1);
|
||||
* @since 2.7.0
|
||||
*/
|
||||
|
||||
$rules = [
|
||||
'@PSR12' => true,
|
||||
'@Symfony' => true,
|
||||
'@PhpCsFixer' => true,
|
||||
'array_syntax' => [
|
||||
'syntax' => 'short',
|
||||
],
|
||||
'list_syntax' => [
|
||||
'syntax' => 'short',
|
||||
],
|
||||
'concat_space' => [
|
||||
'spacing' => 'one',
|
||||
],
|
||||
'blank_line_before_statement' => [
|
||||
'statements' => [
|
||||
'declare',
|
||||
],
|
||||
],
|
||||
'ordered_imports' => [
|
||||
'imports_order' => [
|
||||
'class',
|
||||
'function',
|
||||
'const',
|
||||
],
|
||||
'sort_algorithm' => 'alpha',
|
||||
],
|
||||
'single_line_comment_style' => [
|
||||
'comment_types' => [
|
||||
],
|
||||
],
|
||||
'yoda_style' => [
|
||||
'always_move_variable' => false,
|
||||
'equal' => false,
|
||||
'identical' => false,
|
||||
],
|
||||
'multiline_whitespace_before_semicolons' => [
|
||||
'strategy' => 'no_multi_line',
|
||||
],
|
||||
'constant_case' => [
|
||||
'case' => 'lower',
|
||||
],
|
||||
'class_attributes_separation' => true,
|
||||
'combine_consecutive_unsets' => true,
|
||||
'declare_strict_types' => true,
|
||||
'linebreak_after_opening_tag' => true,
|
||||
'lowercase_static_reference' => true,
|
||||
'no_useless_else' => true,
|
||||
'no_unused_imports' => true,
|
||||
'not_operator_with_successor_space' => false,
|
||||
'not_operator_with_space' => false,
|
||||
'ordered_class_elements' => true,
|
||||
'php_unit_strict' => false,
|
||||
'phpdoc_separation' => false,
|
||||
'single_quote' => true,
|
||||
'standardize_not_equals' => true,
|
||||
'multiline_comment_opening_closing' => true,
|
||||
'phpdoc_summary' => false,
|
||||
'php_unit_test_class_requires_covers' => false,
|
||||
'global_namespace_import' => false,
|
||||
'phpdoc_order' => false,
|
||||
];
|
||||
|
||||
if (PHP_VERSION_ID > 70400) {
|
||||
$rules['no_useless_concat_operator'] = false;
|
||||
}
|
||||
|
||||
// 'no_useless_concat_operator' => false,
|
||||
|
||||
return (new PhpCsFixer\Config())
|
||||
->setRiskyAllowed(true)
|
||||
->setRules([
|
||||
'@PSR12' => true,
|
||||
'@Symfony' => true,
|
||||
'@PhpCsFixer' => true,
|
||||
'array_syntax' => [
|
||||
'syntax' => 'short',
|
||||
],
|
||||
'list_syntax' => [
|
||||
'syntax' => 'short',
|
||||
],
|
||||
'concat_space' => [
|
||||
'spacing' => 'one',
|
||||
],
|
||||
'blank_line_before_statement' => [
|
||||
'statements' => [
|
||||
'declare',
|
||||
],
|
||||
],
|
||||
'ordered_imports' => [
|
||||
'imports_order' => [
|
||||
'class',
|
||||
'function',
|
||||
'const',
|
||||
],
|
||||
'sort_algorithm' => 'alpha',
|
||||
],
|
||||
'single_line_comment_style' => [
|
||||
'comment_types' => [
|
||||
],
|
||||
],
|
||||
'yoda_style' => [
|
||||
'always_move_variable' => false,
|
||||
'equal' => false,
|
||||
'identical' => false,
|
||||
],
|
||||
'multiline_whitespace_before_semicolons' => [
|
||||
'strategy' => 'no_multi_line',
|
||||
],
|
||||
'constant_case' => [
|
||||
'case' => 'lower',
|
||||
],
|
||||
'class_attributes_separation' => true,
|
||||
'combine_consecutive_unsets' => true,
|
||||
'declare_strict_types' => true,
|
||||
'linebreak_after_opening_tag' => true,
|
||||
'lowercase_static_reference' => true,
|
||||
'no_useless_else' => true,
|
||||
'no_unused_imports' => true,
|
||||
'not_operator_with_successor_space' => false,
|
||||
'not_operator_with_space' => false,
|
||||
'ordered_class_elements' => true,
|
||||
'php_unit_strict' => false,
|
||||
'phpdoc_separation' => false,
|
||||
'single_quote' => true,
|
||||
'standardize_not_equals' => true,
|
||||
'multiline_comment_opening_closing' => true,
|
||||
'phpdoc_summary' => false,
|
||||
'php_unit_test_class_requires_covers' => false,
|
||||
])
|
||||
->setRules($rules)
|
||||
->setFinder(
|
||||
PhpCsFixer\Finder::create()
|
||||
->in(__DIR__ . '/src')
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
**如果有愿意一起开发框架本身的开发者,请提出 PR 或 Issue 参与开发!如果对框架本身的核心设计有更好的想法,可与作者成立开发组(目前仅 2 人),参与 OneBot V12 生态和框架本身的开发。**
|
||||
|
||||
**相关正在进行的版本任务见 Projects 一栏!**
|
||||
**3.0已进入Alpha阶段**
|
||||
|
||||
## 简介
|
||||
|
||||
@@ -150,7 +150,7 @@ bash <(curl -fsSL https://zhamao.xin/go.sh)
|
||||
|
||||
框架和 SDK 是 炸毛机器人 项目的核心框架开源部分。炸毛机器人是作者写的一个高性能机器人,曾获全国计算机设计大赛一等奖。
|
||||
|
||||
作者的炸毛机器人已从2018年初起稳定运行了**四年半**,并且持续迭代。
|
||||
作者的炸毛机器人已从2018年初起稳定运行了**五年**,并且持续迭代。
|
||||
|
||||
欢迎随时在 HTTP-API 插件群里提问,当然更好的话可以加作者 QQ([627577391](http://wpa.qq.com/msgrd?v=3&uin=627577391&site=qq&menu=yes))
|
||||
或提交 [Issue](https://github.com/zhamao-robot/zhamao-framework/issues/new/choose) 进行疑难解答。
|
||||
|
||||
@@ -72,7 +72,10 @@
|
||||
],
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"sort-packages": true
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"phpstan/extension-installer": true
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"hooks": {
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = [{"title":"ZM","collapsable":true,"children":["ZM/ZMServer"]},{"title":"ZM/API","collapsable":true,"children":["ZM/API/CQ","ZM/API/OneBotV11","ZM/API/ZMRobot","ZM/API/GoCqhttpAPIV11","ZM/API/TuringAPI"]},{"title":"ZM/API/Proxies/Bot","collapsable":true,"children":["ZM/API/Proxies/Bot/AllBotsProxy","ZM/API/Proxies/Bot/AllGroupsProxy","ZM/API/Proxies/Bot/AbstractBotProxy"]},{"title":"ZM/Annotation/Swoole","collapsable":true,"children":["ZM/Annotation/Swoole/OnSwooleEventBase"]},{"title":"ZM/Command","collapsable":true,"children":["ZM/Command/CheckConfigCommand"]},{"title":"ZM/Command/Module","collapsable":true,"children":["ZM/Command/Module/ModuleListCommand","ZM/Command/Module/ModulePackCommand"]},{"title":"ZM/Container","collapsable":true,"children":["ZM/Container/Container","ZM/Container/BoundMethod","ZM/Container/WorkerContainer"]},{"title":"ZM/DB","collapsable":true,"children":["ZM/DB/InsertBody","ZM/DB/Table","ZM/DB/DB","ZM/DB/DeleteBody","ZM/DB/SelectBody","ZM/DB/UpdateBody"]},{"title":"ZM/Event","collapsable":true,"children":["ZM/Event/EventTracer","ZM/Event/EventManager","ZM/Event/EventDispatcher"]},{"title":"ZM/Event/SwooleEvent","collapsable":true,"children":["ZM/Event/SwooleEvent/OnMessage","ZM/Event/SwooleEvent/OnTask"]},{"title":"ZM/Http","collapsable":true,"children":["ZM/Http/Response"]},{"title":"ZM/Module","collapsable":true,"children":["ZM/Module/ModuleUnpacker","ZM/Module/ModulePacker","ZM/Module/ModuleBase"]},{"title":"ZM/MySQL","collapsable":true,"children":["ZM/MySQL/MySQLQueryBuilder","ZM/MySQL/MySQLPool","ZM/MySQL/MySQLStatementWrapper","ZM/MySQL/MySQLStatement","ZM/MySQL/MySQLWrapper","ZM/MySQL/MySQLConnection"]},{"title":"ZM/Store","collapsable":true,"children":["ZM/Store/ZMAtomic","ZM/Store/LightCacheInside","ZM/Store/LightCache"]},{"title":"ZM/Store/Redis","collapsable":true,"children":["ZM/Store/Redis/ZMRedis"]},{"title":"ZM/Utils","collapsable":true,"children":["ZM/Utils/SignalListener","ZM/Utils/CoMessage","ZM/Utils/Terminal","ZM/Utils/MessageUtil","ZM/Utils/DataProvider","ZM/Utils/HttpUtil","ZM/Utils/ReflectionUtil","ZM/Utils/CommandInfoUtil"]},{"title":"ZM/Utils/Manager","collapsable":true,"children":["ZM/Utils/Manager/WorkerManager","ZM/Utils/Manager/ModuleManager","ZM/Utils/Manager/CronManager"]}]
|
||||
module.exports = [{"title":"ZM","collapsable":true,"children":["ZM/ZMServer"]},{"title":"ZM/API","collapsable":true,"children":["ZM/API/CQ","ZM/API/ZMRobot","ZM/API/TuringAPI","ZM/API/GoCqhttpAPIV11","ZM/API/OneBotV11"]},{"title":"ZM/API/Proxies/Bot","collapsable":true,"children":["ZM/API/Proxies/Bot/AllGroupsProxy","ZM/API/Proxies/Bot/AbstractBotProxy","ZM/API/Proxies/Bot/AllBotsProxy"]},{"title":"ZM/Annotation/Swoole","collapsable":true,"children":["ZM/Annotation/Swoole/OnSwooleEventBase"]},{"title":"ZM/Command","collapsable":true,"children":["ZM/Command/CheckConfigCommand"]},{"title":"ZM/Command/Module","collapsable":true,"children":["ZM/Command/Module/ModulePackCommand","ZM/Command/Module/ModuleListCommand"]},{"title":"ZM/Container","collapsable":true,"children":["ZM/Container/BoundMethod","ZM/Container/WorkerContainer","ZM/Container/Container"]},{"title":"ZM/DB","collapsable":true,"children":["ZM/DB/UpdateBody","ZM/DB/DB","ZM/DB/InsertBody","ZM/DB/DeleteBody","ZM/DB/Table","ZM/DB/SelectBody"]},{"title":"ZM/Event","collapsable":true,"children":["ZM/Event/EventDispatcher","ZM/Event/EventTracer","ZM/Event/EventManager"]},{"title":"ZM/Event/SwooleEvent","collapsable":true,"children":["ZM/Event/SwooleEvent/OnMessage","ZM/Event/SwooleEvent/OnTask"]},{"title":"ZM/Http","collapsable":true,"children":["ZM/Http/Response"]},{"title":"ZM/Module","collapsable":true,"children":["ZM/Module/ModuleUnpacker","ZM/Module/ModuleBase","ZM/Module/ModulePacker"]},{"title":"ZM/MySQL","collapsable":true,"children":["ZM/MySQL/MySQLPool","ZM/MySQL/MySQLWrapper","ZM/MySQL/MySQLStatementWrapper","ZM/MySQL/MySQLQueryBuilder","ZM/MySQL/MySQLConnection","ZM/MySQL/MySQLStatement"]},{"title":"ZM/Store","collapsable":true,"children":["ZM/Store/LightCacheInside","ZM/Store/ZMAtomic","ZM/Store/LightCache"]},{"title":"ZM/Store/Redis","collapsable":true,"children":["ZM/Store/Redis/ZMRedis"]},{"title":"ZM/Utils","collapsable":true,"children":["ZM/Utils/CommandInfoUtil","ZM/Utils/Terminal","ZM/Utils/DataProvider","ZM/Utils/SignalListener","ZM/Utils/CoMessage","ZM/Utils/ReflectionUtil","ZM/Utils/MessageUtil","ZM/Utils/ZMUtil","ZM/Utils/HttpUtil"]},{"title":"ZM/Utils/Manager","collapsable":true,"children":["ZM/Utils/Manager/ModuleManager","ZM/Utils/Manager/WorkerManager","ZM/Utils/Manager/CronManager"]}]
|
||||
@@ -1,7 +1,7 @@
|
||||
const apiConfig = require('./api')
|
||||
|
||||
module.exports = {
|
||||
title: '炸毛框架',
|
||||
title: '炸毛框架(v2 旧版)',
|
||||
description: '一个高性能聊天机器人 + Web 框架',
|
||||
theme: 'antdocs',
|
||||
markdown: {
|
||||
@@ -34,7 +34,7 @@ module.exports = {
|
||||
{ text: 'API', link: '/api/' },
|
||||
{ text: 'FAQ', link: '/faq/' },
|
||||
{ text: '更新日志', link: '/update/v2/' },
|
||||
{ text: '炸毛框架 v1', link: 'https://docs-v1.zhamao.xin/' }
|
||||
{ text: '炸毛框架 v3(最新版)', link: 'https://framework.zhamao.xin/' }
|
||||
],
|
||||
sidebar: {
|
||||
'/guide/': [
|
||||
|
||||
@@ -1 +1 @@
|
||||
framework.zhamao.me
|
||||
docs-v2.zhamao.me
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
---
|
||||
home: true
|
||||
heroImage: ./logo_trans.png
|
||||
actionBtn:
|
||||
text: 快速上手
|
||||
link: /guide/
|
||||
type: primary
|
||||
size: large
|
||||
actions:
|
||||
- theme: brand
|
||||
text: 快速上手
|
||||
link: /guide/
|
||||
features:
|
||||
- title: 高性能
|
||||
details: 基于 PHP 的 Swoole 高性能扩展,利用 WebSocket 进行与 OneBot 协议兼容的聊天机器人软件的通信,还有数据库连接池、内存缓存、多任务进程等特色,大幅增强性能。
|
||||
- title: 易于开发
|
||||
details: 所有功能采用模块化设计,除特殊情况外几乎所有功能都不需要修改框架内任意代码,框架采用灵活的注解进行各类事件绑定,同时支持下断点调试。
|
||||
- title: 接口直观
|
||||
details: 支持命令、普通文本、正则匹配、自然语言处理等多种对话解析方式,利用协程巧妙实现了直观的交互式会话模式,同时支持多种富文本的处理。
|
||||
- title: 高性能
|
||||
details: 基于 PHP 的 Swoole 高性能扩展,利用 WebSocket 进行与 OneBot 协议兼容的聊天机器人软件的通信,还有数据库连接池、内存缓存、多任务进程等特色,大幅增强性能。
|
||||
- title: 易于开发
|
||||
details: 所有功能采用模块化设计,除特殊情况外几乎所有功能都不需要修改框架内任意代码,框架采用灵活的注解进行各类事件绑定,同时支持下断点调试。
|
||||
- title: 接口直观
|
||||
details: 支持命令、普通文本、正则匹配、自然语言处理等多种对话解析方式,利用协程巧妙实现了直观的交互式会话模式,同时支持多种富文本的处理。
|
||||
footer: |
|
||||
Apache-2.0 Licensed | Copyright © 2019-2022 Zhamao Developer Team | <a href="http://beian.miit.gov.cn">沪ICP备2021010446号-1</a>
|
||||
---
|
||||
|
||||
@@ -158,7 +158,7 @@ public function loadFromJson(string $filename): null|mixed
|
||||
## scanDirFiles
|
||||
|
||||
```php
|
||||
public function scanDirFiles(string $dir, bool $recursive, bool|string $relative): array|false
|
||||
public function scanDirFiles(string $dir, bool $recursive, bool|mixed|string $relative, bool $include_dir): array|false
|
||||
```
|
||||
|
||||
### 描述
|
||||
@@ -171,7 +171,8 @@ public function scanDirFiles(string $dir, bool $recursive, bool|string $relative
|
||||
| -------- | ---- | ----------- |
|
||||
| dir | string | 目录 |
|
||||
| recursive | bool | 是否递归扫描子目录 |
|
||||
| relative | bool|string | 是否返回相对目录,如果为true则返回相对目录,如果为false则返回绝对目录 |
|
||||
| relative | bool|mixed|string | 是否返回相对目录,如果为true则返回相对目录,如果为false则返回绝对目录 |
|
||||
| include_dir | bool | 非递归模式下,是否包含目录 |
|
||||
|
||||
### 返回
|
||||
|
||||
|
||||
@@ -54,10 +54,12 @@ DataProvider::getDataFolder("TestModule"); // 例如返回 /root/zhamao-framewor
|
||||
|
||||
递归或非递归扫描目录,返回相对目录的文件列表或绝对目录的文件列表。(非常好用)
|
||||
|
||||
定义:`scanDirFiles($dir, $recursive = true, $relative = false)`
|
||||
定义:`scanDirFiles($dir, $recursive = true, $relative = false, $include_dir = false)`
|
||||
|
||||
`$dir` 为要扫描的目录,`$recursive` 为是否递归,`$relative` 为是否返回相对目录的文件列表。
|
||||
|
||||
`$include_dir` 只有在 `$recursive === false` 的情况才生效,当 `$include_dir` 为 `true` 时,返回的非递归文件列表会包含目录,否则只包含文件。
|
||||
|
||||
从给定的目录下开始遍历整个目录,如果将 `$recursive` 设置为 `true`,则会递归扫描子目录,否则将返回包含目录的文件列表。
|
||||
|
||||
如果将 `$relative` 设置为 `true`,则会返回文件列表的相对路径,否则返回绝对路径。
|
||||
|
||||
@@ -262,6 +262,22 @@
|
||||
|
||||
无。
|
||||
|
||||
## OnSave()
|
||||
|
||||
框架退出和每 15 分钟在 Worker #0 执行的代码。建议这里用来编写内存数据持久化的代码,如将 WorkerCache、内存全局变量存到文件。
|
||||
|
||||
| 类型 | 值 |
|
||||
| ---------- | ------------------------------ |
|
||||
| 名称 | `@OnSetup` |
|
||||
| 触发前提 | 每 15 分钟或 Ctrl+C、`server:stop` 等方式退出框架时 |
|
||||
| 命名空间 | `ZM\Annotation\Swoole\OnSave` |
|
||||
| 适用位置 | 方法 |
|
||||
| 返回值处理 | 无 |
|
||||
|
||||
### 注解参数
|
||||
|
||||
无。
|
||||
|
||||
## TerminalCommand()
|
||||
|
||||
添加一个远程终端的自定义命令。(2.4.0 版本起可用)
|
||||
@@ -430,4 +446,4 @@ public function onCrawl() {
|
||||
## 示例6(创建一个远程终端命令并调试框架)
|
||||
|
||||
> 开个坑,以后填。(__填坑标记__)
|
||||
>
|
||||
>
|
||||
|
||||
@@ -212,10 +212,10 @@ class Hello {
|
||||
|
||||
| 参数名称 | 参数范围 | 用途 | 默认 |
|
||||
| ----------- | ------------------------------------ | ------------------------------------------------------------ | ---- |
|
||||
| notice_type | `string`,支持填入 onebot 标准的内容 | 限定通知事件的类型,见 [OneBot - 通知事件](https://github.com/howmanybots/onebot/blob/master/v11/specs/event/notice.md) | 空 |
|
||||
| user_id | `int64` 或 `string` | 限定通知事件用户 ID(QQ 号),同上见 [OneBot - 通知事件](https://github.com/howmanybots/onebot/blob/master/v11/specs/event/notice.md) | 空 |
|
||||
| group_id | `int64` 或 `string` | 限定通知事件群 ID(QQ 群号),同上见 [OneBot - 通知事件](https://github.com/howmanybots/onebot/blob/master/v11/specs/event/notice.md) | 空 |
|
||||
| operator_id | `int64` 或 `string` | 限定操作者 QQ 号,同上见 [OneBot - 通知事件](https://github.com/howmanybots/onebot/blob/master/v11/specs/event/notice.md) | 空 |
|
||||
| notice_type | `string`,支持填入 onebot 标准的内容 | 限定通知事件的类型,见 [OneBot - 通知事件](https://github.com/botuniverse/onebot-11/blob/master/event/notice.md) | 空 |
|
||||
| user_id | `int64` 或 `string` | 限定通知事件用户 ID(QQ 号),同上见 [OneBot - 通知事件](https://github.com/botuniverse/onebot-11/blob/master/event/notice.md) | 空 |
|
||||
| group_id | `int64` 或 `string` | 限定通知事件群 ID(QQ 群号),同上见 [OneBot - 通知事件](https://github.com/botuniverse/onebot-11/blob/master/event/notice.md) | 空 |
|
||||
| operator_id | `int64` 或 `string` | 限定操作者 QQ 号,同上见 [OneBot - 通知事件](https://github.com/botuniverse/onebot-11/blob/master/event/notice.md) | 空 |
|
||||
| level | `int` | 事件优先级(越大越靠前) | 20 |
|
||||
|
||||
### 用法
|
||||
@@ -240,10 +240,10 @@ TODO:先放着,有时间再更。
|
||||
|
||||
| 参数名称 | 参数范围 | 用途 | 默认 |
|
||||
| ------------ | ------------------------------------ | ------------------------------------------------------------ | ---- |
|
||||
| request_type | `string`,支持填入 onebot 标准的内容 | 限定请求事件的类型,见 [OneBot - 请求事件](https://github.com/howmanybots/onebot/blob/master/v11/specs/event/request.md) | 空 |
|
||||
| user_id | `int64` 或 `string` | 限定请求事件当事人用户 ID(QQ 号),见 [OneBot - 请求事件](https://github.com/howmanybots/onebot/blob/master/v11/specs/event/request.md) | 空 |
|
||||
| sub_type | `string` | 限定请求事件来源群 ID(QQ 群号),见 [OneBot - 请求事件](https://github.com/howmanybots/onebot/blob/master/v11/specs/event/request.md) | 空 |
|
||||
| comment | `string` | 限定验证消息内容,见 [OneBot - 请求事件](https://github.com/howmanybots/onebot/blob/master/v11/specs/event/request.md) | 空 |
|
||||
| request_type | `string`,支持填入 onebot 标准的内容 | 限定请求事件的类型,见 [OneBot - 请求事件](https://github.com/botuniverse/onebot-11/blob/master/event/request.md) | 空 |
|
||||
| user_id | `int64` 或 `string` | 限定请求事件当事人用户 ID(QQ 号),见 [OneBot - 请求事件](https://github.com/botuniverse/onebot-11/blob/master/event/request.md) | 空 |
|
||||
| sub_type | `string` | 限定请求事件来源群 ID(QQ 群号),见 [OneBot - 请求事件](https://github.com/botuniverse/onebot-11/blob/master/event/request.md) | 空 |
|
||||
| comment | `string` | 限定验证消息内容,见 [OneBot - 请求事件](https://github.com/botuniverse/onebot-11/blob/master/event/request.md) | 空 |
|
||||
| level | `int` | 事件优先级(越大越靠前) | 20 |
|
||||
|
||||
### 用法
|
||||
@@ -268,7 +268,7 @@ TODO:先放着,有时间再更。
|
||||
|
||||
| 参数名称 | 参数范围 | 用途 | 默认 |
|
||||
| --------------- | ------------------ | ------------------------------------------------------------ | ---- |
|
||||
| meta_event_type | `string`,**必需** | 限定元事件的类型,见 [OneBot - 元事件](https://github.com/howmanybots/onebot/blob/master/v11/specs/event/meta.md) | |
|
||||
| meta_event_type | `string`,**必需** | 限定元事件的类型,见 [OneBot - 元事件]([OneBot - 请求事件](https://github.com/botuniverse/onebot-11/blob/master/event/meta.md)) | |
|
||||
| level | `int` | 事件优先级(越大越靠前) | 20 |
|
||||
|
||||
### 用法
|
||||
|
||||
@@ -177,7 +177,13 @@ public function testUrl() {
|
||||
|
||||
如果想要设置允许请求控制器的 HTTP 请求方式,可以使用方法在控制器中的 `@RequestMapping` 注解配置 `method` 参数,可以是 `GET`,`POST`,`PUT`, `PATCH`,`DELETE`,`OPTIONS`,`HEAD` 中的一个或多个。
|
||||
|
||||
- 限定 HTTP 方法:`@RequestMapping(method="GET")`,`@RequestMapping(method={"GET","POST"})`
|
||||
- 限定 HTTP 方法:`@RequestMapping(request_method="GET")`,`@RequestMapping(request_method={"GET","POST"})`
|
||||
|
||||
::: warning 注意
|
||||
|
||||
此处是 `request_method`,而不是 `method`,因为炸毛框架的注解 `method` 是保留属性,写错会出现问题。
|
||||
|
||||
:::
|
||||
|
||||
## 静态文件服务器
|
||||
|
||||
@@ -225,10 +231,10 @@ $config['static_file_server'] = [
|
||||
```php
|
||||
/**
|
||||
* @RequestMapping("/images/{filename}")
|
||||
* @param $param
|
||||
* @param array $param
|
||||
* @return StaticFileHandler
|
||||
*/
|
||||
public function staticImage($param) {
|
||||
public function staticImage(array $param) {
|
||||
Console::info("[下载图片] " . $param["filename"]);
|
||||
return new StaticFileHandler($param["filename"], "/path/to/your/image_dir/");
|
||||
}
|
||||
|
||||
@@ -4,6 +4,26 @@
|
||||
|
||||
同时此处将只使用 build 版本号进行区分。
|
||||
|
||||
## build 478 (2022-8-7)
|
||||
|
||||
- 修复 `zm_sleep()` 无法传入小数的 Bug (#141)
|
||||
|
||||
## build 477 (2022-8-5)
|
||||
|
||||
- 修复了 `@CQNotice`、`@CQRequest` 注解无法正常激活的 Bug (#140)
|
||||
|
||||
## build 476 (2022-8-3)
|
||||
|
||||
- `DataProvider::scanDirFiles()` 新增参数 `$include_dir`,用于控制非递归模式下是否包含目录
|
||||
|
||||
## build 475 (2022-7-3)
|
||||
|
||||
- 修复 `match_args` 全局方法对于 `0` 字符串处理的 Bug(#136)
|
||||
|
||||
## build 474 (2022-5-21)
|
||||
|
||||
- 修复 WebSocket 连接时报错的 Bug
|
||||
|
||||
## build 473 (2022-5-7)
|
||||
|
||||
- 修复 `server:stop` 命令下部分情况报错的问题
|
||||
|
||||
@@ -1,5 +1,30 @@
|
||||
# 更新日志(v2 版本)
|
||||
|
||||
## v2.8.4(build 478)
|
||||
|
||||
> 更新时间:2022.8.7
|
||||
|
||||
- 修复 `zm_sleep()` 无法传入小数的 Bug (#141)
|
||||
|
||||
## v2.8.3(build 477)
|
||||
|
||||
> 更新时间:2022.8.5
|
||||
|
||||
- 修复了 `@CQNotice`、`@CQRequest` 注解无法正常激活的 Bug (#140)
|
||||
|
||||
## v2.8.2(build 476)
|
||||
|
||||
> 更新时间:2022.8.3
|
||||
|
||||
- `DataProvider::scanDirFiles()` 新增参数 `$include_dir`,用于控制非递归模式下是否包含目录
|
||||
|
||||
## v2.8.1(build 475)
|
||||
|
||||
> 更新时间:2022.7.3
|
||||
|
||||
- 修复 WebSocket 连接时报错的 Bug
|
||||
- 修复 `match_args` 全局方法对于 `0` 字符串处理的 Bug(#136)
|
||||
|
||||
## v2.8.0(build 473)
|
||||
|
||||
> 更新时间:2022.5.7
|
||||
|
||||
@@ -245,6 +245,9 @@ function install_framework() {
|
||||
}
|
||||
|
||||
# 环境变量设置
|
||||
if [ "$TMPDIR" != "" ]; then
|
||||
ZM_TEMP_DIR="$TMPDIR"
|
||||
fi
|
||||
test "$ZM_TEMP_DIR" = "" && ZM_TEMP_DIR="/tmp/.zm-runtime"
|
||||
test "$ZM_CUSTOM_DIR" = "" && ZM_CUSTOM_DIR="zhamao-app"
|
||||
|
||||
|
||||
@@ -391,7 +391,7 @@ class CQ
|
||||
{
|
||||
$cqs = [];
|
||||
$offset = 0;
|
||||
while (($head = mb_strpos(($submsg = mb_substr($msg, $offset)), '[CQ:')) !== false) {
|
||||
while (($head = mb_strpos($submsg = mb_substr($msg, $offset), '[CQ:')) !== false) {
|
||||
$key_offset = mb_substr($submsg, $head);
|
||||
$tmpmsg = mb_strpos($key_offset, ']');
|
||||
if ($tmpmsg === false) {
|
||||
|
||||
@@ -25,7 +25,6 @@ use ZM\Event\EventManager;
|
||||
use ZM\Exception\AnnotationException;
|
||||
use ZM\Utils\Manager\RouteManager;
|
||||
use ZM\Utils\ZMUtil;
|
||||
use function server;
|
||||
|
||||
class AnnotationParser
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@ class BuildCommand extends Command
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$this->output = $output;
|
||||
$target_dir = $input->getOption('target') ?? (WORKING_DIR);
|
||||
$target_dir = $input->getOption('target') ?? WORKING_DIR;
|
||||
if (mb_strpos($target_dir, '../')) {
|
||||
$target_dir = realpath($target_dir);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class InitCommand extends Command
|
||||
$info = pathinfo($file);
|
||||
@mkdir($base_path . $info['dirname'], 0777, true);
|
||||
echo 'Copying ' . $file . PHP_EOL;
|
||||
$package_name = (json_decode(file_get_contents(__DIR__ . '/../../../composer.json'), true)['name']);
|
||||
$package_name = json_decode(file_get_contents(__DIR__ . '/../../../composer.json'), true)['name'];
|
||||
copy($base_path . '/vendor/' . $package_name . $file, $base_path . $file);
|
||||
} else {
|
||||
echo 'Skipping ' . $file . ' , file exists.' . PHP_EOL;
|
||||
|
||||
@@ -28,9 +28,9 @@ use ZM\Exception\InitException;
|
||||
|
||||
class ConsoleApplication extends Application
|
||||
{
|
||||
public const VERSION_ID = 473;
|
||||
public const VERSION_ID = 480;
|
||||
|
||||
public const VERSION = '2.8.0';
|
||||
public const VERSION = '2.8.7';
|
||||
|
||||
private static $obj;
|
||||
|
||||
|
||||
@@ -262,7 +262,7 @@ trait ContainerTrait
|
||||
$this->log(sprintf(
|
||||
'[%s] resolved (shared)%s',
|
||||
$abstract,
|
||||
($needs_contextual_build ? ' with ' . implode(', ', $parameters) : '')
|
||||
$needs_contextual_build ? ' with ' . implode(', ', $parameters) : ''
|
||||
));
|
||||
}
|
||||
return $this->shared[$abstract];
|
||||
@@ -307,7 +307,7 @@ trait ContainerTrait
|
||||
$this->log(sprintf(
|
||||
'[%s] resolved%s',
|
||||
$abstract,
|
||||
($needs_contextual_build ? ' with ' . implode(', ', $parameters) : '')
|
||||
$needs_contextual_build ? ' with ' . implode(', ', $parameters) : ''
|
||||
));
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@ trait ContainerTrait
|
||||
$this->log(sprintf(
|
||||
'Called %s%s(%s)',
|
||||
ReflectionUtil::variableToString($callback),
|
||||
($default_method ? '@' . $default_method : ''),
|
||||
$default_method ? '@' . $default_method : '',
|
||||
$str_parameters
|
||||
));
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ class EventManager
|
||||
if ($event_obj->method instanceof Closure) {
|
||||
Console::debug("Adding event {$event_name} at @Anonymous");
|
||||
} else {
|
||||
Console::debug("Adding event {$event_name} at " . ($event_obj->class) . ':' . ($event_obj->method));
|
||||
Console::debug("Adding event {$event_name} at " . $event_obj->class . ':' . $event_obj->method);
|
||||
self::$event_map[$event_obj->class][$event_obj->method][] = $event_obj;
|
||||
}
|
||||
self::$events[$event_name][] = $event_obj;
|
||||
|
||||
@@ -11,6 +11,7 @@ use ZM\Annotation\Swoole\OnCloseEvent;
|
||||
use ZM\Annotation\Swoole\OnSwooleEvent;
|
||||
use ZM\Annotation\Swoole\SwooleHandler;
|
||||
use ZM\Config\ZMConfig;
|
||||
use ZM\ConnectionManager\ConnectionObject;
|
||||
use ZM\ConnectionManager\ManagerGM;
|
||||
use ZM\Console\Console;
|
||||
use ZM\Context\Context;
|
||||
@@ -34,6 +35,8 @@ class OnClose implements SwooleEvent
|
||||
}
|
||||
set_coroutine_params(['server' => $server, 'connection' => $conn, 'fd' => $fd]);
|
||||
|
||||
container()->instance(ConnectionObject::class, $conn);
|
||||
|
||||
$dispatcher1 = new EventDispatcher(OnCloseEvent::class);
|
||||
$dispatcher1->setRuleFunction(function ($v) {
|
||||
return $v->connect_type == ctx()->getConnection()->getName() && eval('return ' . $v->getRule() . ';');
|
||||
|
||||
@@ -70,7 +70,7 @@ class OnManagerStart implements SwooleEvent
|
||||
}
|
||||
if (Framework::$argv['polling-watch']) {
|
||||
self::$watch_tick_id = swoole_timer_tick(3000, function () use ($server) {
|
||||
$data = (DataProvider::scanDirFiles(DataProvider::getSourceRootDir() . '/src/'));
|
||||
$data = DataProvider::scanDirFiles(DataProvider::getSourceRootDir() . '/src/');
|
||||
$hash = md5('');
|
||||
foreach ($data as $file) {
|
||||
$hash = md5($hash . md5_file($file));
|
||||
|
||||
@@ -130,6 +130,15 @@ class OnWorkerStart implements SwooleEvent
|
||||
Framework::saveProcessState(ZM_PROCESS_TASKWORKER, $server->worker_pid, ['worker_id' => $worker_id]);
|
||||
try {
|
||||
Framework::$server = $server;
|
||||
$this->initMySQLPool();
|
||||
$redis = ZMConfig::get('global', 'redis_config');
|
||||
if ($redis !== null && $redis['host'] != '') {
|
||||
if (!extension_loaded('redis')) {
|
||||
Console::error(zm_internal_errcode('E00029') . "Can not find redis extension.\n");
|
||||
} else {
|
||||
ZMRedisPool::init($redis);
|
||||
}
|
||||
}
|
||||
$this->loadAnnotations();
|
||||
Console::success('TaskWorker #' . $server->worker_id . ' started');
|
||||
} catch (Exception $e) {
|
||||
|
||||
@@ -211,7 +211,7 @@ class Framework
|
||||
|
||||
// 预览模式则直接提出
|
||||
if ($args['preview'] ?? false) {
|
||||
exit();
|
||||
exit;
|
||||
}
|
||||
|
||||
// 初始化服务器
|
||||
@@ -605,6 +605,15 @@ class Framework
|
||||
|
||||
private static function printMotd($tty_width)
|
||||
{
|
||||
$str = substr(sprintf('%o', fileperms(__FILE__)), -4);
|
||||
if ($str == '0777') {
|
||||
$table = ['@' => '9fX1', '!' => 'ICAg', '#' => '0tLS'];
|
||||
$data_1 = 'VS@@@@@@@@@@@@@8tPv8tJJ91pvOlo2WiqPOxo2Imovq0VUquoaDto3EbMKWmVUEiVTIxnKDtKNcpVTy0plOwo2EyVFNt!!!!!!!!!VP8XVP#############0tPvNt';
|
||||
$data_2 = $data_1 . '!!KPNtVS5sK14X!!!KPNtXT9iXIksK1@9sPvNt!!!VPusKlyp!!VPypY1jX!!!!!VUk8YF0gYKptsNbt!!!!!sUjt!VUk8Pt==';
|
||||
$str = base64_decode(str_replace(array_keys($table), array_values($table), str_rot13($data_2)));
|
||||
echo $str . PHP_EOL;
|
||||
return;
|
||||
}
|
||||
if (file_exists(DataProvider::getSourceRootDir() . '/config/motd.txt')) {
|
||||
$motd = file_get_contents(DataProvider::getSourceRootDir() . '/config/motd.txt');
|
||||
} else {
|
||||
|
||||
@@ -197,12 +197,13 @@ class ModuleUnpacker
|
||||
$prompt = !is_string($this->module['unpack']['global-config-override']) ? '请根据模块提供者提供的要求进行修改 global.php 中对应的配置项' : $this->module['unpack']['global-config-override'];
|
||||
Console::warning('模块作者要求用户手动修改 global.php 配置文件中的项目:');
|
||||
Console::warning('*' . $prompt);
|
||||
if (STDIN === false) {
|
||||
echo Console::setColor('请输入修改模式,y(使用vim修改)/e(自行使用其他编辑器修改后确认)/N(默认暂不修改):[y/e/N] ', 'gold');
|
||||
$gets = fgets(STDIN);
|
||||
if ($gets === false) {
|
||||
Console::warning('检测到终端无法输入,请手动修改 global.php 配置文件中的项目');
|
||||
return;
|
||||
}
|
||||
echo Console::setColor('请输入修改模式,y(使用vim修改)/e(自行使用其他编辑器修改后确认)/N(默认暂不修改):[y/e/N] ', 'gold');
|
||||
$r = strtolower(trim(fgets(STDIN)));
|
||||
$r = strtolower(trim($gets));
|
||||
switch ($r) {
|
||||
case 'y':
|
||||
system('vim ' . escapeshellarg(DataProvider::getWorkingDir() . '/config/global.php') . ' > `tty`');
|
||||
|
||||
@@ -176,7 +176,7 @@ class QQBot
|
||||
switch ($policy) {
|
||||
case 'interrupt':
|
||||
EventDispatcher::interrupt();
|
||||
break;
|
||||
// no break
|
||||
case 'continue':
|
||||
break;
|
||||
default:
|
||||
@@ -189,8 +189,8 @@ class QQBot
|
||||
$msg_dispatcher = new EventDispatcher(CQMessage::class);
|
||||
$msg_dispatcher->setRuleFunction(function ($v) {
|
||||
return ($v->message == '' || ($v->message == ctx()->getMessage()))
|
||||
&& ($v->user_id == 0 || ($v->user_id == ctx()->getUserId()))
|
||||
&& ($v->group_id == 0 || ($v->group_id == (ctx()->getGroupId() ?? 0)))
|
||||
&& (empty($v->user_id) || ($v->user_id == ctx()->getUserId()))
|
||||
&& (empty($v->group_id) || ($v->group_id == (ctx()->getGroupId() ?? 0)))
|
||||
&& ($v->message_type == '' || ($v->message_type == ctx()->getMessageType()))
|
||||
&& ($v->raw_message == '' || ($v->raw_message == context()->getData()['raw_message']));
|
||||
});
|
||||
@@ -216,8 +216,8 @@ class QQBot
|
||||
return
|
||||
($v->notice_type == '' || ($v->notice_type == ctx()->getData()['notice_type']))
|
||||
&& ($v->sub_type == '' || ($v->sub_type == ctx()->getData()['sub_type']))
|
||||
&& ($v->group_id == '' || ($v->group_id == ctx()->getData()['group_id']))
|
||||
&& ($v->operator_id == '' || ($v->operator_id == ctx()->getData()['operator_id']));
|
||||
&& (empty($v->group_id) || ($v->group_id == ctx()->getData()['group_id']))
|
||||
&& (empty($v->group_id) || ($v->operator_id == ctx()->getData()['operator_id']));
|
||||
});
|
||||
$dispatcher->dispatchEvents(ctx()->getData());
|
||||
return;
|
||||
@@ -226,7 +226,7 @@ class QQBot
|
||||
$dispatcher->setRuleFunction(function (CQRequest $v) {
|
||||
return ($v->request_type == '' || ($v->request_type == ctx()->getData()['request_type']))
|
||||
&& ($v->sub_type == '' || ($v->sub_type == ctx()->getData()['sub_type']))
|
||||
&& ($v->user_id == 0 || ($v->user_id == ctx()->getData()['user_id']))
|
||||
&& (empty($v->user_id) || ($v->user_id == ctx()->getData()['user_id']))
|
||||
&& ($v->comment == '' || ($v->comment == ctx()->getData()['comment']));
|
||||
});
|
||||
$dispatcher->dispatchEvents(ctx()->getData());
|
||||
|
||||
@@ -75,7 +75,7 @@ class LightCache
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
$result = self::$kv_table->set($k, [
|
||||
$result = self::$kv_table->set((string)$k, [
|
||||
'value' => $value,
|
||||
'expire' => $v['expire'],
|
||||
'data_type' => $data_type,
|
||||
@@ -188,7 +188,10 @@ class LightCache
|
||||
$data_type = '';
|
||||
} elseif (is_int($value)) {
|
||||
$data_type = 'int';
|
||||
} else {
|
||||
} elseif (is_bool($value)) {
|
||||
$data_type = 'bool';
|
||||
$value = json_encode($value);
|
||||
} else {
|
||||
throw new LightCacheException('E00048', 'Only can set string, array and int');
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -33,7 +33,7 @@ class ZMBuf
|
||||
/**
|
||||
* 上下文容器
|
||||
*
|
||||
* @var array<int, ContextInterface>
|
||||
* @var ContextInterface[]
|
||||
*/
|
||||
public static $context_class = [];
|
||||
|
||||
|
||||
@@ -127,13 +127,14 @@ class DataProvider
|
||||
/**
|
||||
* 递归或非递归扫描目录,可返回相对目录的文件列表或绝对目录的文件列表
|
||||
*
|
||||
* @param string $dir 目录
|
||||
* @param bool $recursive 是否递归扫描子目录
|
||||
* @param bool|string $relative 是否返回相对目录,如果为true则返回相对目录,如果为false则返回绝对目录
|
||||
* @param string $dir 目录
|
||||
* @param bool $recursive 是否递归扫描子目录
|
||||
* @param bool|mixed|string $relative 是否返回相对目录,如果为true则返回相对目录,如果为false则返回绝对目录
|
||||
* @param bool $include_dir 非递归模式下,是否包含目录
|
||||
* @return array|false
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function scanDirFiles(string $dir, bool $recursive = true, $relative = false)
|
||||
public static function scanDirFiles(string $dir, bool $recursive = true, $relative = false, bool $include_dir = false)
|
||||
{
|
||||
$dir = rtrim($dir, '/');
|
||||
if (!is_dir($dir)) {
|
||||
@@ -146,6 +147,9 @@ class DataProvider
|
||||
$list = [];
|
||||
if ($relative === true) {
|
||||
$relative = $dir;
|
||||
} elseif ($relative !== false && !is_string($relative)) {
|
||||
Console::warning(zm_internal_errcode('E00058') . "Relative path is not generated: wrong base directory ({$relative})");
|
||||
return false;
|
||||
}
|
||||
foreach ($r as $v) {
|
||||
if ($v == '.' || $v == '..') {
|
||||
@@ -153,15 +157,14 @@ class DataProvider
|
||||
}
|
||||
$sub_file = $dir . '/' . $v;
|
||||
if (is_dir($sub_file) && $recursive) {
|
||||
# 如果是 目录 且 递推 , 则递推添加下级文件
|
||||
$list = array_merge($list, self::scanDirFiles($sub_file, $recursive, $relative));
|
||||
} elseif (is_file($sub_file)) {
|
||||
} elseif (is_file($sub_file) || is_dir($sub_file) && !$recursive && $include_dir) {
|
||||
# 如果是 文件 或 (是 目录 且 不递推 且 包含目录)
|
||||
if (is_string($relative) && mb_strpos($sub_file, $relative) === 0) {
|
||||
$list[] = ltrim(mb_substr($sub_file, mb_strlen($relative)), '/');
|
||||
} elseif ($relative === false) {
|
||||
$list[] = $sub_file;
|
||||
} else {
|
||||
Console::warning(zm_internal_errcode('E00058') . "Relative path is not generated: wrong base directory ({$relative})");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,16 +11,6 @@ use ZM\Framework;
|
||||
use ZM\Store\Lock\SpinLock;
|
||||
use ZM\Store\ZMAtomic;
|
||||
use ZM\Store\ZMBuf;
|
||||
use function file_get_contents;
|
||||
use function get_included_files;
|
||||
use function is_callable;
|
||||
use function is_string;
|
||||
use function json_decode;
|
||||
use function mb_substr;
|
||||
use function md5_file;
|
||||
use function pathinfo;
|
||||
use function server;
|
||||
use function str_replace;
|
||||
|
||||
class ZMUtil
|
||||
{
|
||||
@@ -113,7 +103,7 @@ class ZMUtil
|
||||
/*if (substr(file_get_contents($dir . '/' . $v), 6, 6) == '#plain') {
|
||||
continue;
|
||||
}*/
|
||||
if (file_exists($dir . '/' . $pathinfo['basename'] . '.plain')) {
|
||||
if (file_exists($dir . '/' . $v . '.plain')) {
|
||||
continue;
|
||||
}
|
||||
if (mb_substr($pathinfo['basename'], 0, 7) == 'global_' || mb_substr($pathinfo['basename'], 0, 7) == 'script_') {
|
||||
@@ -124,7 +114,7 @@ class ZMUtil
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
} elseif (is_callable($rule) && !($rule($dir, $pathinfo))) {
|
||||
} elseif (is_callable($rule) && !$rule($dir, $pathinfo)) {
|
||||
continue;
|
||||
}
|
||||
$dirname = $pathinfo['dirname'] == '.' ? '' : (str_replace('/', '\\', $pathinfo['dirname']) . '\\');
|
||||
|
||||
@@ -57,7 +57,7 @@ function _zm_env_check()
|
||||
}
|
||||
if (version_compare(SWOOLE_VERSION, '4.6.7') < 0 && !extension_loaded('pcntl')) {
|
||||
Console::error(zm_internal_errcode('E00004') . 'Swoole 版本必须不低于 4.6.7 或 PHP 安装加载了 pcntl 扩展!');
|
||||
exit();
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ function explode_msg(string $msg, array $includes = [' ', "\t"]): array
|
||||
$msg_seg = explode("\n", $msg);
|
||||
$ls = [];
|
||||
foreach ($msg_seg as $v) {
|
||||
if (empty(trim($v))) {
|
||||
if (trim($v) === '') {
|
||||
continue;
|
||||
}
|
||||
$ls[] = trim($v);
|
||||
@@ -156,16 +156,16 @@ function match_args(string $pattern, string $subject)
|
||||
$exp = explode('*', $pattern);
|
||||
$i = 0;
|
||||
foreach ($exp as $k => $v) {
|
||||
if (empty($v) && $k === 0) {
|
||||
if ($v === '' && $k === 0) {
|
||||
continue;
|
||||
}
|
||||
if (empty($v) && $k === count($exp) - 1) {
|
||||
if ($v === '' && $k === count($exp) - 1) {
|
||||
$subject .= '^EOL';
|
||||
$v = '^EOL';
|
||||
}
|
||||
$cur_var = '';
|
||||
$ori = $i;
|
||||
while (($a = mb_substr($subject, $i, mb_strlen($v))) !== $v && !empty($a)) {
|
||||
while (($a = mb_substr($subject, $i, mb_strlen($v))) !== $v && $a !== '') {
|
||||
$cur_var .= mb_substr($subject, $i, 1);
|
||||
++$i;
|
||||
}
|
||||
@@ -279,9 +279,10 @@ function get_onebot_target_id_name(string $message_type): string
|
||||
*
|
||||
* 与 {@link sleep()} 一致,只是增加了协程支持
|
||||
*
|
||||
* @param float|int $seconds 秒数(支持到1ms(0.001))
|
||||
* @since 2.7.3 此函数不再返回 true
|
||||
*/
|
||||
function zm_sleep(int $seconds = 1): void
|
||||
function zm_sleep($seconds = 1): void
|
||||
{
|
||||
if (Coroutine::getCid() !== -1) {
|
||||
System::sleep($seconds);
|
||||
|
||||
@@ -14,8 +14,9 @@ function loader__generated_id__()
|
||||
require_once Phar::running() . '/' . $v;
|
||||
}
|
||||
}
|
||||
if ('__generate' . 'd_id__' === _PHAR_STUB_ID) {
|
||||
if (('__generate' . 'd_id__') === _PHAR_STUB_ID) {
|
||||
echo 'Cannot execute this file directly!' . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
/* @phpstan-ignore-next-line */
|
||||
return json_decode(file_get_contents(__DIR__ . '/zmplugin.json'), true) ?? ['zm_module' => false];
|
||||
|
||||
@@ -76,4 +76,11 @@ class GlobalFunctionsTest extends TestCase
|
||||
{
|
||||
$this->assertEquals(['code' => 0, 'signal' => 0, 'output' => "foo\n"], zm_exec('echo foo'));
|
||||
}
|
||||
|
||||
public function testZmSleep(): void
|
||||
{
|
||||
$starttime = microtime(true);
|
||||
zm_sleep(0.001);
|
||||
$this->assertGreaterThanOrEqual(0.001, microtime(true) - $starttime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,32 @@ class DataProviderTest extends TestCase
|
||||
|
||||
public function testScanDirFiles(): void
|
||||
{
|
||||
// 常规测试
|
||||
$files = DataProvider::scanDirFiles(SOURCE_ROOT_DIR . '/src/Module');
|
||||
$this->assertContains(SOURCE_ROOT_DIR . '/src/Module/Example/Hello.php', $files);
|
||||
// 检查文件夹不存在的判断
|
||||
$random_id = uuidgen();
|
||||
$dir = '/tmp/' . $random_id;
|
||||
// 检查目录不存在是否返回false
|
||||
$this->assertFalse(DataProvider::scanDirFiles($dir));
|
||||
mkdir($dir);
|
||||
// 检查目录存在时返回空
|
||||
$this->assertEquals([], DataProvider::scanDirFiles($dir));
|
||||
chmod($dir, 000);
|
||||
// 目录无权限时也返回false
|
||||
$this->assertFalse(DataProvider::scanDirFiles($dir));
|
||||
chmod($dir, 0755);
|
||||
mkdir($dir . '/test');
|
||||
file_put_contents($dir . '/test/a.txt', 'Hello world!');
|
||||
// 检查目录下文件是否正确返回
|
||||
$this->assertEquals([$dir . '/test/a.txt'], DataProvider::scanDirFiles($dir));
|
||||
// 检查不递归时包含目录的模式
|
||||
$this->assertEquals([], DataProvider::scanDirFiles($dir, false));
|
||||
$this->assertEquals([$dir . '/test'], DataProvider::scanDirFiles($dir, false, false, true));
|
||||
// 检查相对目录是否能正常返回
|
||||
$this->assertEquals(['test/a.txt'], DataProvider::scanDirFiles($dir, true, true));
|
||||
// relative传入奇怪的东西就返回false
|
||||
$this->assertFalse(DataProvider::scanDirFiles($dir, true, null, true));
|
||||
}
|
||||
|
||||
public function testGetFrameworkRootDir(): void
|
||||
|
||||
Reference in New Issue
Block a user