Compare commits

...

13 Commits
2.6.0 ... 2.6.4

Author SHA1 Message Date
crazywhalecc
74050c46e7 update to 2.6.4 (build 432) 2021-12-25 19:21:41 +08:00
3ed1cb665a update to build 431 2021-12-22 14:39:46 +08:00
crazywhalecc
a6f33ba69d update to build 430 2021-12-08 21:29:38 +08:00
Jerry Ma
176b690417 Update v2.md 2021-12-07 13:28:21 +08:00
Jerry Ma
e22b1b90ec Update build-update.md 2021-12-07 13:27:33 +08:00
Jerry Ma
a3c560790c Merge pull request #55 from zhamao-robot/fix/cqafter
update to build 429
2021-12-07 13:25:55 +08:00
570e2108dd - 新增配置项 onebot.message_command_policy
- 新增 CQCommand 阻断策略的自定义配置功能
- 修复 CQAfter 无法正常使用的 bug #53
2021-12-07 13:21:29 +08:00
Jerry Ma
59c0d95e5d Create 2_Feature_request.yaml 2021-12-07 12:34:18 +08:00
Jerry Ma
9ceaecdc02 Update README.md 2021-12-07 12:17:47 +08:00
Jerry Ma
19d50898ef Create 1_Bug_report.yaml 2021-12-07 12:15:49 +08:00
Jerry Ma
5b62ca62ae Update README.md 2021-11-17 00:28:54 +08:00
fb528d30ce update docs 2021-11-16 16:51:05 +08:00
5f2d5ed334 update to build 428 2021-11-16 16:49:32 +08:00
26 changed files with 542 additions and 88 deletions

View File

@@ -0,0 +1,38 @@
name: 🐛 漏洞BUG报告
description: ⚠️ 请不要直接在此提交安全漏洞
labels: bug
body:
- type: input
id: affected-versions
attributes:
label: 受影响版本
placeholder: x.y.z
validations:
required: true
- type: textarea
id: description
attributes:
label: 描述
description: 请详细地描述您的问题
validations:
required: true
- type: textarea
id: reproduce-steps
attributes:
label: 复现步骤
description: |
请尽可能地提供可以复现此步骤的漏洞。
如果步骤过长或难以描述,您可以自行建立一个用于复现漏洞的仓库。
validations:
required: true
- type: textarea
id: possible-solution
attributes:
label: 解决方案
description: 如果您对这个漏洞的成因或修复有任何意见的话,请在此提出
- type: textarea
id: additional-context
attributes:
label: 附加信息
description: 其他可能有帮助的信息,如日志、截图等

View File

@@ -0,0 +1,19 @@
name: 🚀 功能建议
description: 新功能、改进的意见、草案
labels: enhancement
body:
- type: textarea
id: description
attributes:
label: 描述
description: 请提供简洁清楚的描述
validations:
required: true
- type: textarea
id: example
attributes:
label: 例子
description: |
一个简单的例子,展示该功能将如何被使用(包括代码、配置文件等)
如果这是针对已有功能的改进,请展示改进前后使用方式(或效能)的对比

1
.gitignore vendored
View File

@@ -12,6 +12,7 @@ composer.lock
.daemon_pid
/runtime/
/tmp/
/temp/
/ext/go-cqhttp/data/
/ext/go-cqhttp/logs/
/ext/go-cqhttp/config.hjson

View File

@@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Reload Zhamao Server" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="./zhamao server:reload &amp;&amp; exit" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="" />
<option name="SCRIPT_OPTIONS" value="" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="true" />
<option name="EXECUTE_SCRIPT_FILE" value="false" />
<envs />
<method v="2" />
</configuration>
</component>

View File

@@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Zhamao Server" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="./zhamao server" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="./zhamao" />
<option name="SCRIPT_OPTIONS" value="server" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="true" />
<option name="EXECUTE_SCRIPT_FILE" value="false" />
<envs />
<method v="2" />
</configuration>
</component>

View File

@@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Stop Zhamao Server" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="./zhamao server:stop &amp;&amp; exit" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="" />
<option name="SCRIPT_OPTIONS" value="" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="true" />
<option name="EXECUTE_SCRIPT_FILE" value="false" />
<envs />
<method v="2" />
</configuration>
</component>

View File

@@ -110,4 +110,10 @@ vendor/bin/start server
在贡献代码时,请保管好自己的全局配置文件中的敏感信息,请勿将带有个人信息的配置文件上传 GitHub 等网站。
![star](https://starchart.cc/zhamao-robot/zhamao-framework.svg)
感谢 JetBrains 为此开源项目提供 PhpStorm 开发工具支持:
<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/PhpStorm.svg" width="300">
感谢 [php-libonebot](https://github.com/botuniverse/php-libonebot) 开发者 @sunxyw 中为项目开发规范化提出的一些建议。
<!-- ![star](https://starchart.cc/zhamao-robot/zhamao-framework.svg) -->

View File

@@ -123,7 +123,8 @@ $config['onebot'] = [
'status' => true,
'single_bot_mode' => false,
'message_level' => 99,
'message_convert_string' => true
'message_convert_string' => true,
'message_command_policy' => 'interrupt',
];
/** 一个远程简易终端使用nc直接连接即可但是不建议开放host为0.0.0.0(远程连接) */

View File

@@ -128,3 +128,52 @@ public function onStart() {
( 其实还是很聪明的!
</chat-box>
### strToArray()
`string` 类型的消息文本转换为 `array` 格式。
定义:`strToArray($msg, bool $ignore_space = true, bool $trim_text = false)`
参数 `$msg` 为带 OB/CQ 码的字符串消息,如 `你好啊,[CQ:at,qq=123]`
参数 `$ignore_space``false` 时,转换的数组内会包含空 `text` 段。
参数 `$trim_text``true` 时,会自动去除 `text` 段消息头尾的换行符和空格。
这个命令转换的数组格式符合 OneBot 11/12 标准,但细节上可能会与不同 OneBot 实现有所差异。
```php
$str = "你好啊,[CQ:at,qq=123]";
$arr = \ZM\Utils\MessageUtil::strToArray($str);
```
转换结果参考如下:
```json
[
{
"type": "text",
"data": {
"text": "你好啊,"
}
},
{
"type": "at",
"data": {
"qq": "123"
}
}
]
```
### arrayToStr()
`array` 格式的消息内容转换为字符串 + CQ 码的形式。
定义:`arrayToStr(array $array)`
```php
// 我们使用上边的 $arr 作为传入值。
$new_str = \ZM\Utils\MessageUtil::arrayToStr($arr);
// 结果:"你好啊,[CQ:at,qq=123]"
```

View File

@@ -769,6 +769,21 @@ vardump($result["retcode"]); //如果成功撤回,输出 int(0)
响应数据:无
### getExtendedAPI()
用来调用 OneBot 标准之外扩展出来的自定义 API。与下方 `callExtendedAPI` 不同的是,为了方便用户使用,炸毛框架内置了热门使用并且相对稳定的机器人客户端的专有 API。
目前内置了 `go-cqhttp` 频道相关的扩充 API。
使用示例:`getExtendedAPI('go-cqhttp')->getGuildList()`
使用示例2`getExtendedAPI()->sendGuildChannelMsg($guild_id, $channel_id, '频道的消息')`
唯一一个参数做保留,用于选择不同客户端,目前仅支持 `go-cqhttp`,所以缺省也默认为 `go-cqhttp`。
!!! warning "注意"
由于不同版本的扩展 API 变化可能会很大,改动较多,炸毛框架不会将对应扩展方法写入文档,具体调用情况可根据 IDE 自动补全中的文档或对应类的注释查看。
### callExtendedAPI() (扩充 API
用来调用 OneBot 标准之外扩展出来的自定义 API。

View File

@@ -56,6 +56,8 @@
| `swoole_coroutine_hook_flags` | Swoole 启动时一键协程化 Hook 的 Flag 值,详见 [一键协程化](http://wiki.swoole.com/#/runtime?id=%e5%87%bd%e6%95%b0%e5%8e%9f%e5%9e%8b) | `SWOOLE_HOOK_ALL & (~SWOOLE_HOOK_CURL)` |
| `swoole_server_mode` | Swoole Server 启动的进程模式,有 `SWOOLE_PROCESS``SWOOLE_BASE` 两种,见 [启动方式](http://wiki.swoole.com/#/learn?id=swoole_process) | `SWOOLE_PROCESS` |
| `middleware_error_policy` | 中间件错误处理策略,见 [中间件 - 错误处理策略](../../event/middleware/#_6) | 1 |
| `reload_delay_time` | 框架 reload 重载命令接收后延迟的时间毫秒0 为不等待) | 800 |
| `global_middleware_binding` | 给注解事件绑定全局中间件,见 [中间件 - 全局中间件](../../event/middleware/#_6) | `[]` |
### 子表 **light_cache**
@@ -106,11 +108,13 @@
### 子表 onebot
| 配置名称 | 说明 | 默认值 |
| ----------------- | ------------------------------------------------------------ | ------ |
| `status` | 是否开启 OneBot 标准机器人解析功能 | true |
| `single_bot_mode` | 是否开启单机器人模式 | false |
| `message_level` | 机器人的 WebSocket 事件在 Swoole 原生事件 `@OnMessageEvent` 中的等级(越高说明越被优先处理) | 99999 |
| 配置名称 | 说明 | 默认值 |
| ------------------------ | ------------------------------------------------------------ | ------ |
| `status` | 是否开启 OneBot 标准机器人解析功能 | true |
| `single_bot_mode` | 是否开启单机器人模式 | false |
| `message_level` | 机器人的 WebSocket 事件在 Swoole 原生事件 `@OnMessageEvent` 中的等级(越高说明越被优先处理) | 99 |
| `message_convert_string` | 是否将数组格式的消息转换为字符串以保证与旧版本的兼容性 | true |
| `message_command_policy` | CQCommand命令匹配后执行流程`interrupt` 为不执行后续 CQMessage`continue` 为继续 | `interrupt` |
### 子表 remote_terminal

View File

@@ -70,5 +70,6 @@
| E00068 | 模块解包时无法正常拷贝文件 | 检查文件夹是否正常可以创建和写入。 |
| E00069 | 框架不能启动两个 ConsoleApplication 实例 | 不要重复使用 `new ConsoleApplication()`。 |
| E00070 | 框架找不到 `zm_data` 目录 | 检查配置中指定的 `zm_data` 目录是否存在。 |
| E00071 | 框架找不到对应类型的 API 调用类 | 检查 `getExtendedAPI($name)` 传入的 `$name` 是否正确 |
| E99999 | 未知错误 | |

View File

@@ -4,6 +4,34 @@
同时此处将只使用 build 版本号进行区分。
## build 432 (2021-12-25)
- 新增 GoCqhttpAPI 包,用于支持额外的 OneBot ActionAPI
- 修复 MySQL 查询器中 `fetchOne()` 方法无法正确返回值的 Bug
- 修复 Swoole Hook 因配置不当无法正确使用的 Bug
## build 431 (2021-12-22)
- 修复 Issue #50
- 新增 PhpStorm IDE 直接运行框架的脚本
## build 430 (2021-12-8)
- 删除调试信息
- 修复 #56 中关于数据库组件的 Bug
## build 429 (2021-12-7)
- 新增配置项 `onebot`.`message_command_policy`
- 新增 CQCommand 阻断策略的自定义配置功能
- 修复 CQAfter 无法正常使用的 bug #53
## build 428 (2021-11-16)
- 修复 `ctx()->waitMessage()` 在 array 消息模式下无法正确返回消息字符串的问题
- 新增 `ctx()->getArrayMessage()``ctx()->getStringMessage()` 两个方法
- 修复注解事件 `CQCommand``CQMessage` 在 array 消息模式下无法正确解析的 Bug
## build 427 (2021-11-16)
- 新增全局中间件,可在全局配置文件中设置

View File

@@ -1,5 +1,38 @@
# 更新日志v2 版本)
## v2.6.4build 432
> 更新时间2021.12.25
- 新增 GoCqhttpAPI 包,用于支持额外的 OneBot ActionAPI
- 修复 MySQL 查询器中 `fetchOne()` 方法无法正确返回值的 Bug
- 修复 Swoole Hook 因配置不当无法正确使用的 Bug
- 修复 Issue #50
- 新增 PhpStorm IDE 直接运行框架的脚本
## v2.6.3 (build 430)
> 更新时间2021.12.8
- 删除调试信息
- 修复 #56 中关于数据库组件的 Bug
## v2.6.2 (build 429)
> 更新时间2021.12.7
- 新增配置项 `onebot`.`message_command_policy`
- 新增 CQCommand 阻断策略的自定义配置功能
- 修复 CQAfter 无法正常使用的 bug #53
## v2.6.1 (build 428)
> 更新时间2021.11.16
- 修复 ctx()->waitMessage() 在 array 消息模式下无法正确返回消息字符串的问题
- 新增 ctx()->getArrayMessage() 和 ctx()->getStringMessage() 两个方法
- 修复注解事件 CQCommand 和 CQMessage 在 array 消息模式下无法正确解析的 Bug
## v2.6.0 (build 427)
> 更新时间2021.11.16

2
install-runtime.sh Normal file → Executable file
View File

@@ -55,4 +55,4 @@ if [ $? -ne 0 ]; then
fi
echo "成功下载!" && \
echo -e "PHP使用\truntime/php -v" && \
echo -e "Composer使用\truntime/composer"
echo -e "Composer使用\truntime/composer"

View File

@@ -80,6 +80,12 @@ trait CQAPI
return false;
}
public function getActionName($suffix, string $method) {
$postfix = ($suffix == OneBotV11::API_ASYNC ? '_async' : ($suffix == OneBotV11::API_RATE_LIMITED ? '_rate_limited' : ''));
$func_name = strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $method));
return $func_name . $postfix;
}
public function __call($name, $arguments) {
return false;
}

View File

@@ -0,0 +1,111 @@
<?php
namespace ZM\API;
class GoCqhttpAPIV11
{
const SUPPORT_VERSION = '1.0.0-beta8';
use CQAPI;
private $connection;
private $callback;
private $prefix;
public function __construct($connection, $callback, $prefix)
{
$this->connection = $connection;
$this->callback = $callback;
$this->prefix = $prefix;
}
/**
* 获取频道系统内BOT的资料
* 响应字段nickname, tiny_id, avatar_url
* @link https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E8%8E%B7%E5%8F%96%E9%A2%91%E9%81%93%E7%B3%BB%E7%BB%9F%E5%86%85bot%E7%9A%84%E8%B5%84%E6%96%99
* @return array|bool
*/
public function getGuildServiceProfile()
{
return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__)
], $this->callback);
}
/**
* 获取频道列表
* @link https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E8%8E%B7%E5%8F%96%E9%A2%91%E9%81%93%E5%88%97%E8%A1%A8
* @return array|bool
*/
public function getGuildList() {
return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__)
], $this->callback);
}
/**
* 通过访客获取频道元数据
* @link https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E9%80%9A%E8%BF%87%E8%AE%BF%E5%AE%A2%E8%8E%B7%E5%8F%96%E9%A2%91%E9%81%93%E5%85%83%E6%95%B0%E6%8D%AE
* @param $guild_id
* @return array|bool
*/
public function getGuildMetaByGuest($guild_id) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'guild_id' => $guild_id
]
], $this->callback);
}
/**
* 获取子频道列表
* @link https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E8%8E%B7%E5%8F%96%E5%AD%90%E9%A2%91%E9%81%93%E5%88%97%E8%A1%A8
* @param $guild_id
* @param false $no_cache
* @return array|bool
*/
public function getGuildChannelList($guild_id, bool $no_cache = false) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'guild_id' => $guild_id,
'no_cache' => $no_cache
]
], $this->callback);
}
/**
* 获取频道成员列表
* @link https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E8%8E%B7%E5%8F%96%E9%A2%91%E9%81%93%E6%88%90%E5%91%98%E5%88%97%E8%A1%A8
* @param $guild_id
* @return array|bool
*/
public function getGuildMembers($guild_id) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'guild_id' => $guild_id
]
], $this->callback);
}
/**
* 发送信息到子频道
* @link https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E5%8F%91%E9%80%81%E4%BF%A1%E6%81%AF%E5%88%B0%E5%AD%90%E9%A2%91%E9%81%93
* @param $guild_id
* @param $channel_id
* @param $message
* @return array|bool
*/
public function sendGuildChannelMsg($guild_id, $channel_id, $message) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'guild_id' => $guild_id,
'channel_id' => $channel_id,
'message' => $message
]
], $this->callback);
}
}

View File

@@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpUnused */
namespace ZM\API;
@@ -6,6 +6,7 @@ namespace ZM\API;
use ZM\ConnectionManager\ConnectionObject;
use ZM\ConnectionManager\ManagerGM;
use ZM\Exception\RobotNotFoundException;
use ZM\Exception\ZMKnownException;
/**
* OneBot V11 的 API 实现类
@@ -22,10 +23,10 @@ class OneBotV11
const API_RATE_LIMITED = 2;
/** @var ConnectionObject|null */
private $connection;
protected $connection;
private $callback = true;
private $prefix = 0;
protected $callback = true;
protected $prefix = 0;
/**
* @param $robot_id
@@ -92,7 +93,7 @@ class OneBotV11
*/
public function sendPrivateMsg($user_id, $message, $auto_escape = false) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'user_id' => $user_id,
'message' => $message,
@@ -111,7 +112,7 @@ class OneBotV11
*/
public function sendGroupMsg($group_id, $message, $auto_escape = false) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
'message' => $message,
@@ -131,7 +132,7 @@ class OneBotV11
*/
public function sendMsg($message_type, $target_id, $message, $auto_escape = false) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'message_type' => $message_type,
($message_type == 'private' ? 'user' : $message_type) . '_id' => $target_id,
@@ -149,7 +150,7 @@ class OneBotV11
*/
public function deleteMsg($message_id) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'message_id' => $message_id
]
@@ -164,7 +165,7 @@ class OneBotV11
*/
public function getMsg($message_id) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'message_id' => $message_id
]
@@ -179,7 +180,7 @@ class OneBotV11
*/
public function getForwardMsg($id) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'id' => $id
]
@@ -195,7 +196,7 @@ class OneBotV11
*/
public function sendLike($user_id, $times = 1) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'user_id' => $user_id,
'times' => $times
@@ -213,7 +214,7 @@ class OneBotV11
*/
public function setGroupKick($group_id, $user_id, $reject_add_request = false) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
'user_id' => $user_id,
@@ -232,7 +233,7 @@ class OneBotV11
*/
public function setGroupBan($group_id, $user_id, $duration = 1800) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
'user_id' => $user_id,
@@ -251,7 +252,7 @@ class OneBotV11
*/
public function setGroupAnonymousBan($group_id, $anonymous_or_flag, $duration = 1800) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
(is_string($anonymous_or_flag) ? 'flag' : 'anonymous') => $anonymous_or_flag,
@@ -269,7 +270,7 @@ class OneBotV11
*/
public function setGroupWholeBan($group_id, $enable = true) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
'enable' => $enable
@@ -287,7 +288,7 @@ class OneBotV11
*/
public function setGroupAdmin($group_id, $user_id, $enable = true) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
'user_id' => $user_id,
@@ -305,7 +306,7 @@ class OneBotV11
*/
public function setGroupAnonymous($group_id, $enable = true) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
'enable' => $enable
@@ -323,7 +324,7 @@ class OneBotV11
*/
public function setGroupCard($group_id, $user_id, $card = "") {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
'user_id' => $user_id,
@@ -341,7 +342,7 @@ class OneBotV11
*/
public function setGroupName($group_id, $group_name) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
'group_name' => $group_name
@@ -358,7 +359,7 @@ class OneBotV11
*/
public function setGroupLeave($group_id, $is_dismiss = false) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
'is_dismiss' => $is_dismiss
@@ -377,7 +378,7 @@ class OneBotV11
*/
public function setGroupSpecialTitle($group_id, $user_id, $special_title = "", $duration = -1) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
'user_id' => $user_id,
@@ -397,7 +398,7 @@ class OneBotV11
*/
public function setFriendAddRequest($flag, $approve = true, $remark = "") {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'flag' => $flag,
'approve' => $approve,
@@ -417,7 +418,7 @@ class OneBotV11
*/
public function setGroupAddRequest($flag, $sub_type, $approve = true, $reason = "") {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'flag' => $flag,
'sub_type' => $sub_type,
@@ -433,7 +434,7 @@ class OneBotV11
* @return array|bool|null
*/
public function getLoginInfo() {
return $this->processAPI($this->connection, ['action' => $this->getActionName(__FUNCTION__)], $this->callback);
return $this->processAPI($this->connection, ['action' => $this->getActionName($this->prefix, __FUNCTION__)], $this->callback);
}
/**
@@ -443,9 +444,9 @@ class OneBotV11
* @param bool $no_cache
* @return array|bool|null
*/
public function getStrangerInfo($user_id, $no_cache = false) {
public function getStrangerInfo($user_id, bool $no_cache) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'user_id' => $user_id,
'no_cache' => $no_cache
@@ -460,7 +461,7 @@ class OneBotV11
*/
public function getFriendList() {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__)
'action' => $this->getActionName($this->prefix, __FUNCTION__)
], $this->callback);
}
@@ -473,7 +474,7 @@ class OneBotV11
*/
public function getGroupInfo($group_id, $no_cache = false) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
'no_cache' => $no_cache
@@ -488,7 +489,7 @@ class OneBotV11
*/
public function getGroupList() {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__)
'action' => $this->getActionName($this->prefix, __FUNCTION__)
], $this->callback);
}
@@ -500,9 +501,9 @@ class OneBotV11
* @param bool $no_cache
* @return array|bool|null
*/
public function getGroupMemberInfo($group_id, $user_id, $no_cache = false) {
public function getGroupMemberInfo($group_id, $user_id, bool $no_cache) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
'user_id' => $user_id,
@@ -519,7 +520,7 @@ class OneBotV11
*/
public function getGroupMemberList($group_id) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id
]
@@ -535,7 +536,7 @@ class OneBotV11
*/
public function getGroupHonorInfo($group_id, $type) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'group_id' => $group_id,
'type' => $type
@@ -550,7 +551,7 @@ class OneBotV11
*/
public function getCsrfToken() {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__)
'action' => $this->getActionName($this->prefix, __FUNCTION__)
], $this->callback);
}
@@ -562,7 +563,7 @@ class OneBotV11
*/
public function getCredentials($domain = "") {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'domain' => $domain
]
@@ -578,7 +579,7 @@ class OneBotV11
*/
public function getRecord($file, $out_format) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'file' => $file,
'out_format' => $out_format
@@ -594,7 +595,7 @@ class OneBotV11
*/
public function getImage($file) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'file' => $file
]
@@ -608,7 +609,7 @@ class OneBotV11
*/
public function canSendImage() {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__)
'action' => $this->getActionName($this->prefix, __FUNCTION__)
], $this->callback);
}
@@ -619,7 +620,7 @@ class OneBotV11
*/
public function canSendRecord() {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__)
'action' => $this->getActionName($this->prefix, __FUNCTION__)
], $this->callback);
}
@@ -630,7 +631,7 @@ class OneBotV11
*/
public function getStatus() {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__)
'action' => $this->getActionName($this->prefix, __FUNCTION__)
], $this->callback);
}
@@ -641,7 +642,7 @@ class OneBotV11
*/
public function getVersionInfo() {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__)
'action' => $this->getActionName($this->prefix, __FUNCTION__)
], $this->callback);
}
@@ -653,7 +654,7 @@ class OneBotV11
*/
public function setRestart($delay = 0) {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__),
'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [
'delay' => $delay
]
@@ -667,20 +668,32 @@ class OneBotV11
*/
public function cleanCache() {
return $this->processAPI($this->connection, [
'action' => $this->getActionName(__FUNCTION__)
'action' => $this->getActionName($this->prefix, __FUNCTION__)
], $this->callback);
}
/**
* 获取内置支持的扩展API对象
* 现支持 go-cqhttp 的扩展API
* @param string $package_name
* @return mixed
* @throws ZMKnownException
*/
public function getExtendedAPI(string $package_name = 'go-cqhttp') {
$table = [
'go-cqhttp' => GoCqhttpAPIV11::class,
];
if (isset($table[$package_name])) {
return new $table[$package_name]($this->connection, $this->callback, $this->prefix);
} else {
throw new ZMKnownException(zm_internal_errcode('E00071'), '无法找到对应的调用扩展类');
}
}
public function callExtendedAPI($action, $params = []) {
return $this->processAPI($this->connection, [
'action' => $action,
'params' => $params
], $this->callback);
}
private function getActionName(string $method) {
$prefix = ($this->prefix == self::API_ASYNC ? '_async' : ($this->prefix == self::API_RATE_LIMITED ? '_rate_limited' : ''));
$func_name = strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $method));
return $func_name . $prefix;
}
}

View File

@@ -30,8 +30,8 @@ class ConsoleApplication extends Application
{
private static $obj = null;
const VERSION_ID = 427;
const VERSION = "2.6.0";
const VERSION_ID = 432;
const VERSION = "2.6.4";
/**
* @throws InitException
@@ -75,7 +75,7 @@ class ConsoleApplication extends Application
$composer["autoload"]["psr-4"]["Custom\\"] = "src/Custom";
$r = file_put_contents(WORKING_DIR . "/composer.json", json_encode($composer, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
if ($r !== false) {
echo "成功添加!请运行 composer dump-autoload \n";
echo "成功添加!请运行 'composer dump-autoload'\n";
exit(0);
} else {
echo zm_internal_errcode("E00006") . "添加失败!请按任意键继续!";

View File

@@ -181,7 +181,11 @@ class Context implements ContextInterface
if ($r === false) {
throw new WaitTimeoutException($this, $timeout_prompt);
}
return $r["message"];
if (is_array($r["message"]) && (ZMConfig::get("global", "onebot")["message_convert_string"] ?? true) === true) {
return MessageUtil::arrayToStr($r["message"]);
} else {
return $r["message"];
}
}
/**
@@ -254,4 +258,16 @@ class Context implements ContextInterface
public function getOption() { return self::getCache("match"); }
public function getOriginMessage() { return self::$context[$this->cid]["data"]["message"] ?? null; }
public function getArrayMessage(): array {
$msg = $this->getOriginMessage();
if (is_array($msg)) return $msg;
else return MessageUtil::strToArray($msg);
}
public function getStringMessage(): string {
$msg = $this->getOriginMessage();
if (is_string($msg)) return $msg;
else return MessageUtil::arrayToStr($msg);
}
}

View File

@@ -440,6 +440,7 @@ class Framework
$coroutine_mode = false;
break;
case 'debug-mode':
self::$argv["disable-safe-exit"] = true;
$coroutine_mode = false;
$terminal_id = null;
self::$argv["watch"] = true;
@@ -486,7 +487,7 @@ class Framework
}
}
$global_hook = ZMConfig::get("global", 'runtime')['swoole_coroutine_hook_flags'] ?? (SWOOLE_HOOK_ALL & (~SWOOLE_HOOK_CURL));
if ($coroutine_mode && $global_hook === false) Runtime::enableCoroutine(true, $global_hook);
if ($coroutine_mode) Runtime::enableCoroutine(true, $global_hook);
else Runtime::enableCoroutine(false, SWOOLE_HOOK_ALL);
}

View File

@@ -4,6 +4,7 @@
namespace ZM\Module;
use Exception;
use ZM\Annotation\CQ\CQAfter;
use ZM\Annotation\CQ\CQAPIResponse;
use ZM\Annotation\CQ\CQBefore;
use ZM\Annotation\CQ\CQCommand;
@@ -11,6 +12,7 @@ use ZM\Annotation\CQ\CQMessage;
use ZM\Annotation\CQ\CQMetaEvent;
use ZM\Annotation\CQ\CQNotice;
use ZM\Annotation\CQ\CQRequest;
use ZM\Config\ZMConfig;
use ZM\Event\EventDispatcher;
use ZM\Exception\InterruptException;
use ZM\Exception\WaitTimeoutException;
@@ -59,9 +61,25 @@ class QQBot
}
if (isset($data["post_type"])) $this->dispatchEvents($data);
else $this->dispatchAPIResponse($data);
if (($data["post_type"] ?? "meta_event") != "meta_event") {
$r = $this->dispatchAfterEvents($data); // before在这里执行元事件不执行before为减少不必要的调试日志
if ($r->store === "block") EventDispatcher::interrupt();
}
} /** @noinspection PhpRedundantCatchClauseInspection */ catch (WaitTimeoutException $e) {
if (($data["post_type"] ?? "meta_event") != "meta_event") {
$r = $this->dispatchAfterEvents($data); // before在这里执行元事件不执行before为减少不必要的调试日志
if ($r->store === "block") EventDispatcher::interrupt();
}
$e->module->finalReply($e->getMessage());
} catch (InterruptException $e) {
if (($data["post_type"] ?? "meta_event") != "meta_event") {
$r = $this->dispatchAfterEvents($data); // before在这里执行元事件不执行before为减少不必要的调试日志
if ($r->store === "block") EventDispatcher::interrupt();
}
throw $e;
}
// 这里修复CQAfter不能使用的问题我竟然一直没写绝了
}
/**
@@ -73,11 +91,11 @@ class QQBot
public function dispatchBeforeEvents($data, $time): EventDispatcher {
$before = new EventDispatcher(CQBefore::class);
if ($time === "pre") {
$before->setRuleFunction(function($v) use ($data){
$before->setRuleFunction(function ($v) use ($data) {
return $v->level >= 200 && $v->cq_event == $data["post_type"];
});
} else {
$before->setRuleFunction(function($v) use ($data){
$before->setRuleFunction(function ($v) use ($data) {
return $v->level < 200 && $v->cq_event == $data["post_type"];
});
}
@@ -103,22 +121,33 @@ class QQBot
if (is_string($result)) ctx()->reply($result);
if (ctx()->getCache("has_reply") === true) EventDispatcher::interrupt();
});
$s = MessageUtil::matchCommand(ctx()->getMessage(), ctx()->getData());
$s = MessageUtil::matchCommand(ctx()->getStringMessage(), ctx()->getData());
if ($s->status !== false) {
if (!empty($s->match)) ctx()->setCache("match", $s->match);
$dispatcher->dispatchEvent($s->object, null);
if (is_string($dispatcher->store)) ctx()->reply($dispatcher->store);
if (ctx()->getCache("has_reply") === true) EventDispatcher::interrupt();
if (ctx()->getCache("has_reply") === true) {
$policy = ZMConfig::get("global", "onebot")['message_command_policy'] ?? 'interrupt';
switch ($policy) {
case 'interrupt':
EventDispatcher::interrupt();
break;
case 'continue':
break;
default:
throw new Exception("未知的消息命令策略:" . $policy);
}
}
}
//分发CQMessage事件
$msg_dispatcher = new EventDispatcher(CQMessage::class);
$msg_dispatcher->setRuleFunction(function ($v) {
return ($v->message == '' || ($v->message != '' && $v->message == context()->getData()["message"])) &&
($v->user_id == 0 || ($v->user_id != 0 && $v->user_id == context()->getData()["user_id"])) &&
($v->group_id == 0 || ($v->group_id != 0 && $v->group_id == (context()->getData()["group_id"] ?? 0))) &&
($v->message_type == '' || ($v->message_type != '' && $v->message_type == context()->getData()["message_type"])) &&
($v->raw_message == '' || ($v->raw_message != '' && $v->raw_message == context()->getData()["raw_message"]));
return ($v->message == '' || ($v->message == ctx()->getStringMessage())) &&
($v->user_id == 0 || ($v->user_id == ctx()->getUserId())) &&
($v->group_id == 0 || ($v->group_id == (ctx()->getGroupId() ?? 0))) &&
($v->message_type == '' || ($v->message_type == ctx()->getMessageType())) &&
($v->raw_message == '' || ($v->raw_message == context()->getData()["raw_message"]));
});
$msg_dispatcher->setReturnFunction(function ($result) {
if (is_string($result)) ctx()->reply($result);
@@ -158,6 +187,15 @@ class QQBot
}
}
private function dispatchAfterEvents($data): EventDispatcher {
$after = new EventDispatcher(CQAfter::class);
$after->setRuleFunction(function ($v) use ($data) {
return $v->cq_event == $data["post_type"];
});
$after->dispatchEvents($data);
return $after;
}
/**
* @param $req
* @throws Exception

View File

@@ -17,19 +17,23 @@ class MySQLStatement implements IteratorAggregate, Statement
/** @var PDOStatement|PDOStatementProxy */
private $statement;
public function __construct($obj) {
public function __construct($obj)
{
$this->statement = $obj;
}
public function closeCursor() {
public function closeCursor()
{
return $this->statement->closeCursor();
}
public function columnCount() {
public function columnCount()
{
return $this->statement->columnCount();
}
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = []) {
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = [])
{
if ($arg2 !== null && $arg3 !== [])
return $this->statement->setFetchMode($fetchMode, $arg2, $arg3);
elseif ($arg2 !== null && $arg3 === [])
@@ -40,47 +44,63 @@ class MySQLStatement implements IteratorAggregate, Statement
return $this->statement->setFetchMode($fetchMode);
}
public function fetch($fetchMode = PDO::FETCH_ASSOC, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) {
public function fetch($fetchMode = PDO::FETCH_ASSOC, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{
return $this->statement->fetch($fetchMode, $cursorOrientation, $cursorOffset);
}
public function fetchAll($fetchMode = PDO::FETCH_ASSOC, $fetchArgument = null, $ctorArgs = null) {
return $this->statement->fetchAll($fetchMode, $fetchArgument, $ctorArgs);
public function fetchAll($fetchMode = PDO::FETCH_ASSOC, $fetchArgument = null, $ctorArgs = null)
{
if ($fetchArgument === null && $ctorArgs === null)
return $this->statement->fetchAll($fetchMode);
elseif ($fetchArgument !== null && $ctorArgs === null)
return $this->statement->fetchAll($fetchMode, $fetchArgument);
else
return $this->statement->fetchAll($fetchMode, $fetchArgument, $ctorArgs);
}
public function fetchColumn($columnIndex = 0) {
public function fetchColumn($columnIndex = 0)
{
return $this->statement->fetchColumn($columnIndex);
}
public function bindValue($param, $value, $type = ParameterType::STRING) {
public function bindValue($param, $value, $type = ParameterType::STRING)
{
return $this->statement->bindValue($param, $value, $type);
}
public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null) {
public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null)
{
return $this->statement->bindParam($param, $variable, $type, $length);
}
public function errorCode() {
public function errorCode()
{
return $this->statement->errorCode();
}
public function errorInfo() {
public function errorInfo()
{
return $this->statement->errorInfo();
}
public function execute($params = null) {
public function execute($params = null)
{
return $this->statement->execute($params);
}
public function rowCount() {
public function rowCount()
{
return $this->statement->rowCount();
}
public function getIterator() {
public function getIterator()
{
return new StatementIterator($this);
}
public function current() {
public function current()
{
return $this->statement->current();
}
}

View File

@@ -94,7 +94,7 @@ class MySQLWrapper
* @return false|mixed
* @throws DbException
*/
public function fetchOne(string $query, array $params = [], array $types = []): bool {
public function fetchOne(string $query, array $params = [], array $types = []) {
try {
return $this->connection->fetchOne($query, $params, $types);
} catch (Throwable $e) {

View File

@@ -111,6 +111,9 @@ class MessageUtil
*/
public static function matchCommand($msg, $obj): MatchResult {
$ls = EventManager::$events[CQCommand::class] ?? [];
if (is_array($msg)) {
$msg = self::arrayToStr($msg);
}
$word = self::splitCommand($msg);
$matched = new MatchResult();
foreach ($ls as $v) {

0
zhamao Normal file → Executable file
View File