diff --git a/bin/systemd b/bin/systemd deleted file mode 100644 index a138393f..00000000 --- a/bin/systemd +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env php - 更新时间:2021.3.24 +> 更新时间:2021.3.25 - 新增:检查全局配置文件的命令 - 新增:全局配置文件更新记录 @@ -21,18 +21,18 @@ - 新增:支持添加自定义远程终端指令的 `@TerminalCommand` 注解 - 新增:图灵机器人 API 封装函数 - 新增:ZMUtil 工具杂项类 `getReloadableFiles()` 函数 +- 新增:`vendor/bin/start systemd:generate` 生成 systemd 配置文件的功能 +- 新增:`vendor/bin/start check:config` 检查配置文件更新的命令 +- 新增:`vendor/bin/init` 新增 `--force` 参数,覆盖现有文件重新生成 +- 新增:MessageUtil 新增方法:`addShortCommand()`,用于快速添加静态文本问答回复的 +以下是需要**手动更新**或**更换新写法**的部分: +- 配置文件 `global.php` 中的 `modules` 字段展开,内置模块的配置一律平铺到外面。详见 [更新日志 - 配置文件变更](/update/config)。 +以下是默认机器人直接连接产生的变更: - - -- 修复:部分内部存储存在的内存泄漏问题 -- 新增:remote_terminal(远程终端)内置模块,可以用 nc 直接远程连接框架(弥补原先删除掉的终端输入) -- 新增:`DataProvider::getReloadableFiles()` 返回可通过热重启(reload)来重新加载的 php 文件列表(多用于调试) -- 兼容性变更:**要求最低 Swoole 版本为 4.5.0** -- 优化:reload 和 stop 重载和停止框架的逻辑,防止卡死 -- 新增:远程终端命令支持自定义添加(`@TerminalCommand` 注解) +- 2.4.0 新增了默认回复其他人 at 的消息,如果不需要,请将 `Hello.php` 中的 `changeAt()` 和 `turingAPI()` 方法删除。 ## v2.3.5 (build 398) diff --git a/src/ZM/Command/CheckConfigCommand.php b/src/ZM/Command/CheckConfigCommand.php index 02e2010c..1d12f0c1 100644 --- a/src/ZM/Command/CheckConfigCommand.php +++ b/src/ZM/Command/CheckConfigCommand.php @@ -9,7 +9,7 @@ use Symfony\Component\Console\Output\OutputInterface; class CheckConfigCommand extends Command { - protected static $defaultName = 'check-config'; + protected static $defaultName = 'check:config'; private $need_update = false; @@ -17,14 +17,13 @@ class CheckConfigCommand extends Command $this->setDescription("检查配置文件是否和框架当前版本有更新"); } - /** @noinspection PhpIncludeInspection */ protected function execute(InputInterface $input, OutputInterface $output): int { if (LOAD_MODE !== 1) { $output->writeln("仅限在Composer依赖模式中使用此命令!"); return Command::FAILURE; } - $current_cfg = WORKING_DIR . "/config/"; - $remote_cfg = include_once $current_cfg . "/vendor/zhamao/framework/config/global.php"; + $current_cfg = getcwd() . "/config/"; + $remote_cfg = include_once WORKING_DIR . "/config/global.php"; if (file_exists($current_cfg . "global.php")) { $this->check($remote_cfg, "global.php", $output); } @@ -39,17 +38,23 @@ class CheckConfigCommand extends Command } if ($this->need_update === true) { $output->writeln("有配置文件需要更新,详情见文档 https://framework.zhamao.xin/update/config.md"); + } else { + $output->writeln("配置文件暂无更新!"); } + return Command::SUCCESS; } + /** + * @noinspection PhpIncludeInspection + */ private function check($remote, $local, OutputInterface $out) { - $local_file = include_once WORKING_DIR . "/config/".$local; + $local_file = include_once getcwd() . "/config/".$local; foreach($remote as $k => $v) { + $out->writeln("正在检查".$k.""); if (!isset($local_file[$k])) { - $out->writeln("配置文件 ".$local . " 需要更新!"); + $out->writeln("配置文件 ".$local . " 需要更新!(缺少 `$k` 字段配置)"); $this->need_update = true; - return; } } } diff --git a/src/ZM/Command/InitCommand.php b/src/ZM/Command/InitCommand.php index 6fa35f7b..4701a0f7 100644 --- a/src/ZM/Command/InitCommand.php +++ b/src/ZM/Command/InitCommand.php @@ -26,6 +26,7 @@ class InitCommand extends Command protected function configure() { $this->setDescription("Initialize framework starter | 初始化框架运行的基础文件"); + $this->addOption("force", 'F', null, "强制重制,覆盖现有文件"); $this->setHelp("此命令将会解压以下文件到项目的根目录:\n" . implode("\n", $this->getExtractFiles())); // ... } @@ -34,8 +35,9 @@ class InitCommand extends Command if (LOAD_MODE === 1) { // 从composer依赖而来的项目模式,最基本的需要初始化的模式 $output->writeln("Initializing files"); $base_path = LOAD_MODE_COMPOSER_PATH; + $args = $input->getArgument("force"); foreach ($this->extract_files as $file) { - if (!file_exists($base_path . $file)) { + if (!file_exists($base_path . $file) || $args) { $info = pathinfo($file); @mkdir($base_path . $info["dirname"], 0777, true); echo "Copying " . $file . PHP_EOL; @@ -67,8 +69,8 @@ class InitCommand extends Command } } file_put_contents($base_path . "/composer.json", json_encode($composer, 64 | 128 | 256)); - $output->writeln("Executing composer update command"); - exec("composer update"); + $output->writeln("Executing composer command: `composer dump-autoload`"); + exec("composer dump-autoload"); echo PHP_EOL; } else { echo("Error occurred. Please check your updates.\n"); diff --git a/src/ZM/Command/SystemdCommand.php b/src/ZM/Command/SystemdCommand.php index bf6a804f..53e0195b 100644 --- a/src/ZM/Command/SystemdCommand.php +++ b/src/ZM/Command/SystemdCommand.php @@ -13,8 +13,30 @@ class SystemdCommand extends Command // the name of the command (the part after "bin/console") protected static $defaultName = 'systemd:generate'; + protected function configure() { + $this->setDescription("生成框架的 systemd 配置文件"); + } + protected function execute(InputInterface $input, OutputInterface $output): int { - //TODO: 写一个生成systemd配置的功能,给2.0 + $path = $this->generate(); + $output->writeln("成功生成 systemd 文件,位置:".$path.""); + $output->writeln("有关如何使用 systemd 配置文件,请访问 `https://github.com/zhamao-robot/zhamao-framework/issues/36`"); return Command::SUCCESS; } + + private function generate() { + $s = "[Unit]\nDescription=zhamao-framework Daemon\nAfter=rc-local.service\n\n[Service]\nType=simple"; + $s .= "\nUser=" . exec("whoami"); + $s .= "\nGroup=" . exec("groups | awk '{print $1}'"); + $s .= "\nWorkingDirectory=" . getcwd(); + if (LOAD_MODE == 1) { + $s .= "\nExecStart=" . getcwd() . "/vendor/bin/start server"; + } else { + $s .= "\nExecStart=" . getcwd() . "/bin/start server"; + } + $s .= "\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n"; + @mkdir(getcwd() . "/resources/"); + file_put_contents(getcwd() . "/resources/zhamao.service", $s); + return getcwd() . "/resources/zhamao.service"; + } } diff --git a/src/ZM/ConsoleApplication.php b/src/ZM/ConsoleApplication.php index 21802594..b1c1a729 100644 --- a/src/ZM/ConsoleApplication.php +++ b/src/ZM/ConsoleApplication.php @@ -15,11 +15,12 @@ use ZM\Command\RunServerCommand; use Symfony\Component\Console\Application; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use ZM\Command\SystemdCommand; use ZM\Utils\DataProvider; class ConsoleApplication extends Application { - const VERSION_ID = 399; + const VERSION_ID = 400; const VERSION = "2.4.0"; public function __construct(string $name = 'UNKNOWN') { @@ -74,7 +75,8 @@ class ConsoleApplication extends Application new DaemonStopCommand(), new RunServerCommand(), //运行主服务的指令控制器 new InitCommand(), //初始化用的,用于项目初始化和phar初始化 - new PureHttpCommand() //纯HTTP服务器指令 + new PureHttpCommand(), //纯HTTP服务器指令 + new SystemdCommand() ]); if (LOAD_MODE === 1) { $this->add(new CheckConfigCommand()); diff --git a/src/ZM/Event/EventDispatcher.php b/src/ZM/Event/EventDispatcher.php index 13eba6c7..69db389f 100644 --- a/src/ZM/Event/EventDispatcher.php +++ b/src/ZM/Event/EventDispatcher.php @@ -117,6 +117,17 @@ class EventDispatcher public function dispatchEvent($v, $rule_func = null, ...$params) { $q_c = $v->class; $q_f = $v->method; + if ($q_c === "" && ($q_f instanceof \Closure)) { + if ($this->log) Console::verbose("[事件分发{$this->eid}] 闭包函数的事件触发过程!"); + if ($rule_func !== null && !$rule_func($v)) { + if ($this->log) Console::verbose("[事件分发{$this->eid}] 闭包函数下的 ruleFunc 判断为 false, 拒绝执行此方法。"); + $this->status = self::STATUS_RULE_FAILED; + return false; + } + $this->store = $q_f(...$params); + $this->status = self::STATUS_NORMAL; + return true; + } if ($this->log) Console::verbose("[事件分发{$this->eid}] 正在判断 " . $q_c . "::" . $q_f . " 方法下的 ruleFunc ..."); if ($rule_func !== null && !$rule_func($v)) { if ($this->log) Console::verbose("[事件分发{$this->eid}] " . $q_c . "::" . $q_f . " 方法下的 ruleFunc 判断为 false, 拒绝执行此方法。"); diff --git a/src/ZM/Module/QQBot.php b/src/ZM/Module/QQBot.php index 1985d435..ee3fed76 100644 --- a/src/ZM/Module/QQBot.php +++ b/src/ZM/Module/QQBot.php @@ -103,7 +103,6 @@ class QQBot if (is_string($result)) ctx()->reply($result); if (ctx()->getCache("has_reply") === true) EventDispatcher::interrupt(); }); - zm_dump(ctx()->getData()); $s = MessageUtil::matchCommand(ctx()->getMessage(), ctx()->getData()); if ($s->status !== false) { if (!empty($s->match)) ctx()->setCache("match", $s->match); diff --git a/src/ZM/Utils/MessageUtil.php b/src/ZM/Utils/MessageUtil.php index 0c11814f..7fc501c4 100644 --- a/src/ZM/Utils/MessageUtil.php +++ b/src/ZM/Utils/MessageUtil.php @@ -159,4 +159,10 @@ class MessageUtil } return $matched; } + + public static function addShortCommand($command, string $reply) { + for ($i = 0; $i < ZM_WORKER_NUM; ++$i) { + ProcessManager::sendActionToWorker($i, "add_short_command", [$command, $reply]); + } + } } \ No newline at end of file diff --git a/src/ZM/Utils/ProcessManager.php b/src/ZM/Utils/ProcessManager.php index 973f3d43..3047c1bc 100644 --- a/src/ZM/Utils/ProcessManager.php +++ b/src/ZM/Utils/ProcessManager.php @@ -5,9 +5,11 @@ namespace ZM\Utils; use Co; +use ZM\Annotation\CQ\CQCommand; use ZM\Annotation\Swoole\OnPipeMessageEvent; use ZM\Console\Console; use ZM\Event\EventDispatcher; +use ZM\Event\EventManager; use ZM\Store\LightCache; use ZM\Store\LightCacheInside; use ZM\Store\WorkerCache; @@ -17,6 +19,14 @@ class ProcessManager public static function workerAction($src_worker_id, $data) { $server = server(); switch ($data["action"] ?? '') { + case 'add_short_command': + Console::verbose("Adding short command ".$data["data"][0]); + $obj = new CQCommand(); + $obj->method = quick_reply_closure($data["data"][1]); + $obj->match = $data["data"][0]; + $obj->class = ""; + EventManager::addEvent(CQCommand::class, $obj); + break; case "eval": eval($data["data"]); break; diff --git a/src/ZM/global_functions.php b/src/ZM/global_functions.php index 9b38f3cf..903c6f5c 100644 --- a/src/ZM/global_functions.php +++ b/src/ZM/global_functions.php @@ -394,3 +394,9 @@ function zm_verbose($obj) { Console::verbose($obj); } function zm_error($obj) { Console::error($obj); } function zm_config($name, $key = null) { return ZMConfig::get($name, $key); } + +function quick_reply_closure($reply) { + return function() use ($reply){ + return $reply; + }; +}