update to 2.0.0-b5 version

set modules config to array
add subdir index.html
update Example of Hello.php
add Exception tester for TimerMiddleware.php
add keyword for @CQCommand
rename OnWorkerStart.php to OnStart.php
remove SwooleEventAfter.php
rename HandleEvent.php to SwooleHandler.php
set ZMRobot callback mode default to true
add getNextArg() and getFullArg()
add EventDispatcher.php logger
set Exception all based from ZMException
fix recursive bug for Response.php
add single_bot_mode
add SingletonTrait.php
add bot() function
This commit is contained in:
jerry 2020-12-14 01:24:34 +08:00
parent 1ffb30a471
commit ba5b793db7
35 changed files with 285 additions and 174 deletions

View File

@ -3,7 +3,7 @@
"description": "High performance QQ robot and web server development framework", "description": "High performance QQ robot and web server development framework",
"minimum-stability": "stable", "minimum-stability": "stable",
"license": "Apache-2.0", "license": "Apache-2.0",
"version": "2.0.0-b4", "version": "2.0.0-b5",
"extra": {}, "extra": {},
"authors": [ "authors": [
{ {
@ -35,6 +35,10 @@
"symfony/routing": "^5.1", "symfony/routing": "^5.1",
"symfony/polyfill-php80": "^1.20" "symfony/polyfill-php80": "^1.20"
}, },
"suggest": {
"ext-ctype": "*",
"ext-mbstring": "*"
},
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"ZM\\": "src/ZM", "ZM\\": "src/ZM",
@ -57,4 +61,4 @@
"phpunit/phpunit": "^9.3", "phpunit/phpunit": "^9.3",
"swoole/ide-helper": "@dev" "swoole/ide-helper": "@dev"
} }
} }

View File

@ -50,8 +50,6 @@ $config['sql_config'] = [
'sql_username' => 'name', 'sql_username' => 'name',
'sql_database' => 'db_name', 'sql_database' => 'db_name',
'sql_password' => '', 'sql_password' => '',
'sql_enable_cache' => true,
'sql_reset_cache' => '0300',
'sql_options' => [ 'sql_options' => [
PDO::ATTR_STRINGIFY_FETCHES => false, PDO::ATTR_STRINGIFY_FETCHES => false,
PDO::ATTR_EMULATE_PREPARES => false PDO::ATTR_EMULATE_PREPARES => false
@ -115,7 +113,10 @@ $config['command_register_class'] = [
/** 服务器启用的外部第三方和内部插件 */ /** 服务器启用的外部第三方和内部插件 */
$config['modules'] = [ $config['modules'] = [
'onebot' => true, // QQ机器人事件解析器如果取消此项则默认为 true 开启状态,否则你手动填写 false 才会关闭 'onebot' => [
'status' => true,
'single_bot_mode' => false
], // QQ机器人事件解析器如果取消此项则默认为 true 开启状态,否则你手动填写 false 才会关闭
]; ];
return $config; return $config;

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example page</title>
</head>
<body>
<div style="background: red; width: 100px; height: 100px"></div>
</body>
</html>

View File

@ -8,7 +8,9 @@ use ZM\ConnectionManager\ConnectionObject;
use ZM\Console\Console; use ZM\Console\Console;
use ZM\Annotation\CQ\CQCommand; use ZM\Annotation\CQ\CQCommand;
use ZM\Annotation\Http\RequestMapping; use ZM\Annotation\Http\RequestMapping;
use ZM\Event\EventDispatcher;
use ZM\Store\Redis\ZMRedis; use ZM\Store\Redis\ZMRedis;
use ZM\Utils\ZMUtil;
/** /**
* Class Hello * Class Hello
@ -40,11 +42,20 @@ class Hello
} }
} }
/**
* 使用命令 .reload 发给机器人远程重载,注意将 user_id 换成你自己的 QQ
* @CQCommand(".reload",user_id=627577391)
*/
public function reload() {
ctx()->reply("重启中...");
ZMUtil::reload();
}
/** /**
* @CQCommand("我是谁") * @CQCommand("我是谁")
*/ */
public function whoami() { public function whoami() {
$user = ctx()->getRobot()->setCallback(true)->getLoginInfo(); $user = ctx()->getRobot()->getLoginInfo();
return "你是" . $user["data"]["nickname"] . "QQ号是" . $user["data"]["user_id"]; return "你是" . $user["data"]["nickname"] . "QQ号是" . $user["data"]["user_id"];
} }
@ -121,6 +132,14 @@ class Hello
Console::info("机器人 " . $conn->getOption("connect_id") . " 已断开连接!"); Console::info("机器人 " . $conn->getOption("connect_id") . " 已断开连接!");
} }
/**
* 阻止 Chrome 自动请求 /favicon.ico 导致的多条请求并发和干扰
* @OnSwooleEvent("request",rule="ctx()->getRequest()->server['request_uri'] == '/favicon.ico'",level=200)
*/
public function onRequest() {
EventDispatcher::interrupt();
}
/** /**
* 框架会默认关闭未知的WebSocket链接因为这个绑定的事件你可以根据你自己的需求进行修改 * 框架会默认关闭未知的WebSocket链接因为这个绑定的事件你可以根据你自己的需求进行修改
* @OnSwooleEvent(type="open",rule="connectIsDefault()") * @OnSwooleEvent(type="open",rule="connectIsDefault()")

View File

@ -2,8 +2,9 @@
namespace Module\Middleware; namespace Module\Middleware;
use ZM\Annotation\Http\After; use ZM\Annotation\Http\HandleAfter;
use ZM\Annotation\Http\Before; use ZM\Annotation\Http\HandleBefore;
use ZM\Annotation\Http\HandleException;
use ZM\Annotation\Http\MiddlewareClass; use ZM\Annotation\Http\MiddlewareClass;
use ZM\Console\Console; use ZM\Console\Console;
use ZM\Http\MiddlewareInterface; use ZM\Http\MiddlewareInterface;
@ -19,7 +20,7 @@ class TimerMiddleware implements MiddlewareInterface
private $starttime; private $starttime;
/** /**
* @Before() * @HandleBefore()
* @return bool * @return bool
*/ */
public function onBefore() { public function onBefore() {
@ -28,9 +29,16 @@ class TimerMiddleware implements MiddlewareInterface
} }
/** /**
* @After() * @HandleAfter()
*/ */
public function onAfter() { public function onAfter() {
Console::info("Using " . round((microtime(true) - $this->starttime) * 1000, 2) . " ms."); Console::info("Using " . round((microtime(true) - $this->starttime) * 1000, 2) . " ms.");
} }
/**
* @HandleException(\Exception::class)
*/
public function onException() {
Console::error("Using " . round((microtime(true) - $this->starttime) * 1000, 2) . " ms but an Exception occurred.");
}
} }

View File

@ -24,7 +24,7 @@ class ZMRobot
/** @var ConnectionObject|null */ /** @var ConnectionObject|null */
private $connection; private $connection;
private $callback = null; private $callback = true;
private $prefix = 0; private $prefix = 0;
/** /**
@ -50,6 +50,9 @@ class ZMRobot
return new ZMRobot($r[array_rand($r)]); return new ZMRobot($r[array_rand($r)]);
} }
public static function getFirst() {
}
/** /**
* @return ZMRobot[] * @return ZMRobot[]
*/ */

View File

@ -9,7 +9,7 @@ use ZM\Console\Console;
use ReflectionClass; use ReflectionClass;
use ReflectionException; use ReflectionException;
use ReflectionMethod; use ReflectionMethod;
use ZM\Annotation\Http\{After, Before, Controller, HandleException, Middleware, MiddlewareClass, RequestMapping}; use ZM\Annotation\Http\{HandleAfter, HandleBefore, Controller, HandleException, Middleware, MiddlewareClass, RequestMapping};
use ZM\Annotation\Interfaces\Level; use ZM\Annotation\Interfaces\Level;
use ZM\Annotation\Module\Closed; use ZM\Annotation\Module\Closed;
use ZM\Utils\DataProvider; use ZM\Utils\DataProvider;
@ -287,8 +287,8 @@ class AnnotationParser
foreach ($reflection_class->getMethods() as $vss) { foreach ($reflection_class->getMethods() as $vss) {
$method_annotations = $this->reader->getMethodAnnotations($vss); $method_annotations = $this->reader->getMethodAnnotations($vss);
foreach ($method_annotations as $vsss) { foreach ($method_annotations as $vsss) {
if ($vsss instanceof Before) $result["before"] = $vss->getName(); if ($vsss instanceof HandleBefore) $result["before"] = $vss->getName();
if ($vsss instanceof After) $result["after"] = $vss->getName(); if ($vsss instanceof HandleAfter) $result["after"] = $vss->getName();
if ($vsss instanceof HandleException) { if ($vsss instanceof HandleException) {
$result["exceptions"][$vsss->class_name] = $vss->getName(); $result["exceptions"][$vsss->class_name] = $vss->getName();
} }

View File

@ -25,6 +25,8 @@ class CQCommand extends AnnotationBase implements Level
public $start_with = ""; public $start_with = "";
/** @var string */ /** @var string */
public $end_with = ""; public $end_with = "";
/** @var string */
public $keyword = "";
/** @var string[] */ /** @var string[] */
public $alias = []; public $alias = [];
/** @var string */ /** @var string */

View File

@ -9,11 +9,11 @@ use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
/** /**
* Class After * Class HandleAfter
* @package ZM\Annotation\Http * @package ZM\Annotation\Http
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */
class After extends AnnotationBase class HandleAfter extends AnnotationBase
{ {
} }

View File

@ -4,16 +4,15 @@
namespace ZM\Annotation\Http; namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
/** /**
* Class Before * Class HandleBefore
* @package ZM\Annotation\Http * @package ZM\Annotation\Http
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */
class Before extends AnnotationBase class HandleBefore extends AnnotationBase
{ {
} }

View File

@ -13,6 +13,6 @@ use ZM\Annotation\AnnotationBase;
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */
class ZMSetup extends AnnotationBase class OnSetup extends AnnotationBase
{ {
} }

View File

@ -12,7 +12,7 @@ use ZM\Annotation\AnnotationBase;
* @Annotation * @Annotation
* @Target("ALL") * @Target("ALL")
*/ */
class OnWorkerStart extends AnnotationBase class OnStart extends AnnotationBase
{ {
/** /**
* @var int * @var int

View File

@ -1,76 +0,0 @@
<?php
namespace ZM\Annotation\Swoole;
use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase;
use ZM\Annotation\Interfaces\Level;
use ZM\Annotation\Interfaces\Rule;
/**
* Class SwooleEventAfter
* @Annotation
* @Target("ALL")
* @package ZM\Annotation\Swoole
*/
class SwooleEventAfter extends AnnotationBase implements Rule, Level
{
/**
* @var string
* @Required
*/
public $type;
/** @var string */
public $rule = "";
/** @var int */
public $level = 20;
/**
* @return string
*/
public function getType(): string {
return $this->type;
}
/**
* @param string $type
*/
public function setType(string $type) {
$this->type = $type;
}
/**
* @return string
*/
public function getRule(): string {
return $this->rule;
}
/**
* @param string $rule
*/
public function setRule(string $rule) {
$this->rule = $rule;
}
/**
* @return int
*/
public function getLevel(): int {
return $this->level;
}
/**
* @param int $level
*/
public function setLevel(int $level) {
$this->level = $level;
}
}

View File

@ -9,12 +9,12 @@ use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
/** /**
* Class HandleEvent * Class SwooleHandler
* @package ZM\Annotation\Swoole * @package ZM\Annotation\Swoole
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */
class HandleEvent extends AnnotationBase class SwooleHandler extends AnnotationBase
{ {
/** /**
* @var string * @var string

View File

@ -68,9 +68,6 @@ class ConsoleApplication extends Application
} }
} }
if (!is_dir(DataProvider::getWorkingDir() . '/src/')) {
die("Unable to find source directory.\nMaybe you need to run \"init\"?");
}
ZMConfig::setDirectory(DataProvider::getWorkingDir() . '/config'); ZMConfig::setDirectory(DataProvider::getWorkingDir() . '/config');
ZMConfig::env($args["env"] ?? ""); ZMConfig::env($args["env"] ?? "");
if (ZMConfig::get("global") === false) { if (ZMConfig::get("global") === false) {

View File

@ -149,7 +149,7 @@ class Context implements ContextInterface
} catch (Exception $e) { } catch (Exception $e) {
$r = false; $r = false;
} }
if($r === false) { if ($r === false) {
throw new WaitTimeoutException($this, $timeout_prompt); throw new WaitTimeoutException($this, $timeout_prompt);
} }
return $r["message"]; return $r["message"];
@ -203,7 +203,6 @@ class Context implements ContextInterface
switch ($mode) { switch ($mode) {
case ZM_MATCH_ALL: case ZM_MATCH_ALL:
$p = $arg; $p = $arg;
array_shift($p);
return trim(implode(" ", $p)) == "" ? $this->waitMessage($prompt_msg) : trim(implode(" ", $p)); return trim(implode(" ", $p)) == "" ? $this->waitMessage($prompt_msg) : trim(implode(" ", $p));
case ZM_MATCH_NUMBER: case ZM_MATCH_NUMBER:
foreach ($arg as $k => $v) { foreach ($arg as $k => $v) {
@ -215,9 +214,9 @@ class Context implements ContextInterface
} }
return $this->waitMessage($prompt_msg); return $this->waitMessage($prompt_msg);
case ZM_MATCH_FIRST: case ZM_MATCH_FIRST:
if (isset($arg[1])) { if (isset($arg[0])) {
$a = $arg[1]; $a = $arg[0];
array_splice($arg, 1, 1); array_splice($arg, 0, 1);
ctx()->setCache("match", $arg); ctx()->setCache("match", $arg);
return $a; return $a;
} else { } else {
@ -227,6 +226,22 @@ class Context implements ContextInterface
throw new InvalidArgumentException(); throw new InvalidArgumentException();
} }
/**
* @param string $prompt_msg
* @return int|mixed|string
* @throws InvalidArgumentException
* @throws WaitTimeoutException
*/
public function getNextArg($prompt_msg = "") { return $this->getArgs(ZM_MATCH_FIRST, $prompt_msg); }
/**
* @param string $prompt_msg
* @return int|mixed|string
* @throws InvalidArgumentException
* @throws WaitTimeoutException
*/
public function getFullArg($prompt_msg = "") { return $this->getArgs(ZM_MATCH_ALL, $prompt_msg); }
public function cloneFromParent() { public function cloneFromParent() {
set_coroutine_params(self::$context[Co::getPcid()] ?? self::$context[$this->cid]); set_coroutine_params(self::$context[Co::getPcid()] ?? self::$context[$this->cid]);
return context(); return context();

View File

@ -103,6 +103,10 @@ interface ContextInterface
*/ */
public function getArgs($mode, $prompt_msg); public function getArgs($mode, $prompt_msg);
public function getNextArg($prompt_msg = "");
public function getFullArg($prompt_msg = "");
public function setCache($key, $value); public function setCache($key, $value);
/** /**

View File

@ -7,8 +7,12 @@ namespace ZM\Event;
use Doctrine\Common\Annotations\AnnotationException; use Doctrine\Common\Annotations\AnnotationException;
use Exception; use Exception;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
use ZM\Annotation\CQ\CQMetaEvent; use ZM\Console\Console;
use ZM\Exception\InterruptException; use ZM\Exception\InterruptException;
use ZM\Exception\ZMException;
use ZM\Store\LightCacheInside;
use ZM\Store\Lock\SpinLock;
use ZM\Store\ZMAtomic;
use ZM\Utils\ZMUtil; use ZM\Utils\ZMUtil;
class EventDispatcher class EventDispatcher
@ -19,6 +23,10 @@ class EventDispatcher
private $rule = null; private $rule = null;
/** @var null|callable */ /** @var null|callable */
private $return_func = null; private $return_func = null;
/** @var bool */
private $log = false;
/** @var int */
private $eid = 0;
/** /**
* @throws InterruptException * @throws InterruptException
@ -27,8 +35,32 @@ class EventDispatcher
throw new InterruptException('interrupt'); throw new InterruptException('interrupt');
} }
public static function enableEventTrace($event_class) {
SpinLock::lock("_event_trace");
$list = LightCacheInside::get("wait_api", "event_trace");
$list[$event_class] = true;
LightCacheInside::set("wait_api", "event_trace", $list);
SpinLock::unlock("_event_trace");
}
public static function disableEventTrace($event_class) {
SpinLock::lock("_event_trace");
$list = LightCacheInside::get("wait_api", "event_trace");
unset($list[$event_class]);
LightCacheInside::set("wait_api", "event_trace", $list);
SpinLock::unlock("_event_trace");
}
public function __construct(string $class = '') { public function __construct(string $class = '') {
$this->class = $class; $this->class = $class;
try {
$this->eid = ZMAtomic::get("_event_id")->add(1);
$list = LightCacheInside::get("wait_api", "event_trace");
} catch (ZMException $e) {
$list = [];
}
if (isset($list[$class])) $this->log = true;
if ($this->log) Console::verbose("[事件分发{$this->eid}] 开始分发事件: " . $class);
} }
public function setRuleFunction(callable $rule = null) { public function setRuleFunction(callable $rule = null) {
@ -43,10 +75,13 @@ class EventDispatcher
public function dispatchEvents(...$params) { public function dispatchEvents(...$params) {
try { try {
foreach ((EventManager::$events[$this->class] ?? []) as $v) { foreach ((EventManager::$events[$this->class] ?? []) as $v) {
$result = $this->dispatchEvent($v, $this->rule, ...$params); $result = $this->dispatchEvent($v, $this->rule, ...$params);
if ($result !== false && is_callable($this->return_func)) ($this->return_func)($result); if ($this->log) Console::verbose("[事件分发{$this->eid}] 单一对象 " . $v->class . "::" . $v->method . " 分发结束。");
if ($result !== false && is_callable($this->return_func)) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] 单一对象 " . $v->class . "::" . $v->method . " 正在执行返回值处理函数 ...");
($this->return_func)($result);
}
} }
return true; return true;
} catch (InterruptException $e) { } catch (InterruptException $e) {
@ -67,9 +102,15 @@ class EventDispatcher
public function dispatchEvent(?AnnotationBase $v, $rule_func = null, ...$params) { public function dispatchEvent(?AnnotationBase $v, $rule_func = null, ...$params) {
$q_c = $v->class; $q_c = $v->class;
$q_f = $v->method; $q_f = $v->method;
if ($rule_func !== null && !$rule_func($v)) return false; if ($this->log) Console::verbose("[事件分发{$this->eid}] 正在判断 " . $q_c . "::" . $q_f . " 方法下的 rule ...");
if ($rule_func !== null && !$rule_func($v)) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] " . $q_c . "::" . $q_f . " 方法下的 rule 判断为 false, 拒绝执行此方法。");
return false;
}
if ($this->log) Console::verbose("[事件分发{$this->eid}] " . $q_c . "::" . $q_f . " 方法下的 rule 为真,继续执行方法本身 ...");
if (isset(EventManager::$middleware_map[$q_c][$q_f])) { if (isset(EventManager::$middleware_map[$q_c][$q_f])) {
$middlewares = EventManager::$middleware_map[$q_c][$q_f]; $middlewares = EventManager::$middleware_map[$q_c][$q_f];
if ($this->log) Console::verbose("[事件分发{$this->eid}] " . $q_c . "::" . $q_f . " 方法还绑定了 Middleware" . implode(", ", $middlewares));
$before_result = true; $before_result = true;
$r = []; $r = [];
foreach ($middlewares as $k => $middleware) { foreach ($middlewares as $k => $middleware) {
@ -81,22 +122,34 @@ class EventDispatcher
$r[$k]->class = $q_c; $r[$k]->class = $q_c;
$r[$k]->method = $q_f; $r[$k]->method = $q_f;
if (isset($middleware_obj["before"])) { if (isset($middleware_obj["before"])) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] Middleware 存在前置事件,执行中 ...");
$rs = $middleware_obj["before"]; $rs = $middleware_obj["before"];
$before_result = $r[$k]->$rs(...$params); $before_result = $r[$k]->$rs(...$params);
if ($before_result === false) break; if ($before_result === false) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] Middleware 前置事件为 false停止执行原事件开始执行下一事件。");
break;
} else {
if ($this->log) Console::verbose("[事件分发{$this->eid}] Middleware 前置事件为 true继续执行原事件。");
}
} }
} }
if ($before_result) { if ($before_result) {
try { try {
$q_o = ZMUtil::getModInstance($q_c); $q_o = ZMUtil::getModInstance($q_c);
if ($this->log) Console::verbose("[事件分发{$this->eid}] 正在执行方法 " . $q_c . "::" . $q_f . " ...");
$result = $q_o->$q_f(...$params); $result = $q_o->$q_f(...$params);
} catch (Exception $e) { } catch (Exception $e) {
if ($e instanceof InterruptException) throw $e; if ($e instanceof InterruptException) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] 检测到事件阻断调用,正在跳出事件分发器 ...");
throw $e;
}
if ($this->log) Console::verbose("[事件分发{$this->eid}] 方法 " . $q_c . "::" . $q_f . " 执行过程中抛出了异常,正在倒序查找 Middleware 中的捕获方法 ...");
for ($i = count($middlewares) - 1; $i >= 0; --$i) { for ($i = count($middlewares) - 1; $i >= 0; --$i) {
$middleware_obj = EventManager::$middlewares[$middlewares[$i]]; $middleware_obj = EventManager::$middlewares[$middlewares[$i]];
if (!isset($middleware_obj["exceptions"])) continue; if (!isset($middleware_obj["exceptions"])) continue;
foreach ($middleware_obj["exceptions"] as $name => $method) { foreach ($middleware_obj["exceptions"] as $name => $method) {
if ($e instanceof $name) { if ($e instanceof $name) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] 方法 " . $q_c . "::" . $q_f . " 的异常 " . get_class($e) . " 被 Middleware:" . $middlewares[$i] . " 下的 " . get_class($r[$i]) . "::" . $method . " 捕获。");
$r[$i]->$method($e); $r[$i]->$method($e);
self::interrupt(); self::interrupt();
} }
@ -107,7 +160,9 @@ class EventDispatcher
for ($i = count($middlewares) - 1; $i >= 0; --$i) { for ($i = count($middlewares) - 1; $i >= 0; --$i) {
$middleware_obj = EventManager::$middlewares[$middlewares[$i]]; $middleware_obj = EventManager::$middlewares[$middlewares[$i]];
if (isset($middleware_obj["after"], $r[$i])) { if (isset($middleware_obj["after"], $r[$i])) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] Middleware 存在后置事件,执行中 ...");
$r[$i]->{$middleware_obj["after"]}(...$params); $r[$i]->{$middleware_obj["after"]}(...$params);
if ($this->log) Console::verbose("[事件分发{$this->eid}] Middleware 后置事件执行完毕!");
} }
} }
return $result; return $result;
@ -115,6 +170,7 @@ class EventDispatcher
return false; return false;
} else { } else {
$q_o = ZMUtil::getModInstance($q_c); $q_o = ZMUtil::getModInstance($q_c);
if ($this->log) Console::verbose("[事件分发{$this->eid}] 正在执行方法 " . $q_c . "::" . $q_f . " ...");
return $q_o->$q_f(...$params); return $q_o->$q_f(...$params);
} }
} }

View File

@ -16,7 +16,7 @@ use Swoole\Process;
use Swoole\Timer; use Swoole\Timer;
use ZM\Annotation\AnnotationParser; use ZM\Annotation\AnnotationParser;
use ZM\Annotation\Http\RequestMapping; use ZM\Annotation\Http\RequestMapping;
use ZM\Annotation\Swoole\OnWorkerStart; use ZM\Annotation\Swoole\OnStart;
use ZM\Annotation\Swoole\OnSwooleEvent; use ZM\Annotation\Swoole\OnSwooleEvent;
use ZM\Config\ZMConfig; use ZM\Config\ZMConfig;
use ZM\ConnectionManager\ManagerGM; use ZM\ConnectionManager\ManagerGM;
@ -24,7 +24,7 @@ use ZM\Console\Console;
use Swoole\Http\Request; use Swoole\Http\Request;
use Swoole\Server; use Swoole\Server;
use Swoole\WebSocket\Frame; use Swoole\WebSocket\Frame;
use ZM\Annotation\Swoole\HandleEvent; use ZM\Annotation\Swoole\SwooleHandler;
use ZM\Console\TermColor; use ZM\Console\TermColor;
use ZM\Context\Context; use ZM\Context\Context;
use ZM\Context\ContextInterface; use ZM\Context\ContextInterface;
@ -33,6 +33,7 @@ use ZM\Exception\DbException;
use ZM\Framework; use ZM\Framework;
use ZM\Http\Response; use ZM\Http\Response;
use ZM\Module\QQBot; use ZM\Module\QQBot;
use ZM\Store\LightCacheInside;
use ZM\Store\MySQL\SqlPoolStorage; use ZM\Store\MySQL\SqlPoolStorage;
use ZM\Store\Redis\ZMRedisPool; use ZM\Store\Redis\ZMRedisPool;
use ZM\Store\ZMBuf; use ZM\Store\ZMBuf;
@ -44,7 +45,7 @@ use ZM\Utils\ZMUtil;
class ServerEventHandler class ServerEventHandler
{ {
/** /**
* @HandleEvent("start") * @SwooleHandler("start")
*/ */
public function onStart() { public function onStart() {
global $terminal_id; global $terminal_id;
@ -87,14 +88,14 @@ class ServerEventHandler
} }
/** /**
* @HandleEvent("shutdown") * @SwooleHandler("shutdown")
*/ */
public function onShutdown() { public function onShutdown() {
Console::debug("正在关闭 Master 进程pid=" . posix_getpid()); Console::debug("正在关闭 Master 进程pid=" . posix_getpid());
} }
/** /**
* @HandleEvent("WorkerStop") * @SwooleHandler("WorkerStop")
* @param $server * @param $server
* @param $worker_id * @param $worker_id
*/ */
@ -103,7 +104,7 @@ class ServerEventHandler
} }
/** /**
* @HandleEvent("WorkerStart") * @SwooleHandler("WorkerStart")
* @param Server $server * @param Server $server
* @param $worker_id * @param $worker_id
*/ */
@ -205,12 +206,12 @@ class ServerEventHandler
EventManager::registerTimerTick(); //启动计时器 EventManager::registerTimerTick(); //启动计时器
//ZMBuf::unsetCache("wait_start"); //ZMBuf::unsetCache("wait_start");
set_coroutine_params(["server" => $server, "worker_id" => $worker_id]); set_coroutine_params(["server" => $server, "worker_id" => $worker_id]);
$dispatcher = new EventDispatcher(OnWorkerStart::class); $dispatcher = new EventDispatcher(OnStart::class);
$dispatcher->setRuleFunction(function ($v) { $dispatcher->setRuleFunction(function ($v) {
return server()->worker_id === $v->worker_id || $v->worker_id === -1; return server()->worker_id === $v->worker_id || $v->worker_id === -1;
}); });
$dispatcher->dispatchEvents($server, $worker_id); $dispatcher->dispatchEvents($server, $worker_id);
Console::debug("@OnWorkerStart 执行完毕"); Console::debug("@OnStart 执行完毕");
} catch (Exception $e) { } catch (Exception $e) {
Console::error("Worker加载出错停止服务"); Console::error("Worker加载出错停止服务");
Console::error($e->getMessage() . "\n" . $e->getTraceAsString()); Console::error($e->getMessage() . "\n" . $e->getTraceAsString());
@ -243,7 +244,7 @@ class ServerEventHandler
} }
/** /**
* @HandleEvent("message") * @SwooleHandler("message")
* @param $server * @param $server
* @param Frame $frame * @param Frame $frame
*/ */
@ -266,9 +267,9 @@ class ServerEventHandler
} }
}); });
try { try {
$starttime = microtime(true); //$starttime = microtime(true);
$dispatcher->dispatchEvents($conn); $dispatcher->dispatchEvents($conn);
Console::success("Used ".round((microtime(true) - $starttime) * 1000, 3)." ms!"); //Console::success("Used ".round((microtime(true) - $starttime) * 1000, 3)." ms!");
} catch (Exception $e) { } catch (Exception $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
Console::error("Uncaught exception " . get_class($e) . " when calling \"message\": " . $error_msg); Console::error("Uncaught exception " . get_class($e) . " when calling \"message\": " . $error_msg);
@ -282,7 +283,7 @@ class ServerEventHandler
} }
/** /**
* @HandleEvent("request") * @SwooleHandler("request")
* @param $request * @param $request
* @param $response * @param $response
*/ */
@ -356,7 +357,7 @@ class ServerEventHandler
} }
/** /**
* @HandleEvent("open") * @SwooleHandler("open")
* @param $server * @param $server
* @param Request $request * @param Request $request
*/ */
@ -369,6 +370,7 @@ class ServerEventHandler
$conn = ManagerGM::get($request->fd); $conn = ManagerGM::get($request->fd);
set_coroutine_params(["server" => $server, "request" => $request, "connection" => $conn, "fd" => $request->fd]); set_coroutine_params(["server" => $server, "request" => $request, "connection" => $conn, "fd" => $request->fd]);
$conn->setOption("connect_id", strval($request->header["x-self-id"]) ?? ""); $conn->setOption("connect_id", strval($request->header["x-self-id"]) ?? "");
$dispatcher = new EventDispatcher(OnSwooleEvent::class); $dispatcher = new EventDispatcher(OnSwooleEvent::class);
$dispatcher->setRuleFunction(function ($v) { $dispatcher->setRuleFunction(function ($v) {
if ($v->getRule() == '') { if ($v->getRule() == '') {
@ -380,6 +382,11 @@ class ServerEventHandler
} }
}); });
try { try {
if ($conn->getName() === 'qq' && ZMConfig::get("global", "modules")["onebot"]["status"] === true) {
if (ZMConfig::get("global", "modules")["onebot"]["single_bot_mode"]) {
LightCacheInside::set("connect", "conn_fd", $request->fd);
}
}
$dispatcher->dispatchEvents($conn); $dispatcher->dispatchEvents($conn);
} catch (Exception $e) { } catch (Exception $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
@ -394,7 +401,7 @@ class ServerEventHandler
} }
/** /**
* @HandleEvent("close") * @SwooleHandler("close")
* @param $server * @param $server
* @param $fd * @param $fd
*/ */
@ -404,6 +411,8 @@ class ServerEventHandler
if ($conn === null) return; if ($conn === null) return;
Console::debug("Calling Swoole \"close\" event from fd=" . $fd); Console::debug("Calling Swoole \"close\" event from fd=" . $fd);
set_coroutine_params(["server" => $server, "connection" => $conn, "fd" => $fd]); set_coroutine_params(["server" => $server, "connection" => $conn, "fd" => $fd]);
$dispatcher = new EventDispatcher(OnSwooleEvent::class); $dispatcher = new EventDispatcher(OnSwooleEvent::class);
$dispatcher->setRuleFunction(function ($v) { $dispatcher->setRuleFunction(function ($v) {
if ($v->getRule() == '') { if ($v->getRule() == '') {
@ -415,6 +424,11 @@ class ServerEventHandler
} }
}); });
try { try {
if ($conn->getName() === 'qq' && ZMConfig::get("global", "modules")["onebot"]["status"] === true) {
if (ZMConfig::get("global", "modules")["onebot"]["single_bot_mode"]) {
LightCacheInside::set("connect", "conn_fd", -1);
}
}
$dispatcher->dispatchEvents($conn); $dispatcher->dispatchEvents($conn);
} catch (Exception $e) { } catch (Exception $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
@ -429,7 +443,7 @@ class ServerEventHandler
} }
/** /**
* @HandleEvent("pipeMessage") * @SwooleHandler("pipeMessage")
* @param $server * @param $server
* @param $src_worker_id * @param $src_worker_id
* @param $data * @param $data
@ -462,7 +476,7 @@ class ServerEventHandler
} }
/** /**
* @HandleEvent("task") * @SwooleHandler("task")
*/ */
public function onTask() { public function onTask() {
} }
@ -504,7 +518,7 @@ class ServerEventHandler
//加载插件 //加载插件
$plugins = ZMConfig::get("global", "modules") ?? []; $plugins = ZMConfig::get("global", "modules") ?? [];
if (!isset($plugins["onebot"])) $plugins["onebot"] = true; if (!isset($plugins["onebot"])) $plugins["onebot"] = ["status" => true, "single_bot_mode" => false];
if ($plugins["onebot"]) { if ($plugins["onebot"]) {
$obj = new OnSwooleEvent(); $obj = new OnSwooleEvent();
@ -514,6 +528,11 @@ class ServerEventHandler
$obj->level = 99999; $obj->level = 99999;
$obj->rule = 'connectIsQQ()'; $obj->rule = 'connectIsQQ()';
EventManager::addEvent(OnSwooleEvent::class, $obj); EventManager::addEvent(OnSwooleEvent::class, $obj);
if ($plugins["onebot"]["single_bot_mode"]) {
LightCacheInside::set("connect", "conn_fd", -1);
} else {
LightCacheInside::set("connect", "conn_fd", -2);
}
} }
//TODO: 编写加载外部插件的方式 //TODO: 编写加载外部插件的方式

View File

@ -4,9 +4,7 @@
namespace ZM\Exception; namespace ZM\Exception;
use Exception;
class DbException extends ZMException class DbException extends ZMException
{ {
} }

View File

@ -4,8 +4,6 @@
namespace ZM\Exception; namespace ZM\Exception;
use Exception;
class InterruptException extends ZMException class InterruptException extends ZMException
{ {

View File

@ -4,9 +4,7 @@
namespace ZM\Exception; namespace ZM\Exception;
use Exception;
class InvalidArgumentException extends ZMException class InvalidArgumentException extends ZMException
{ {
} }

View File

@ -4,8 +4,6 @@
namespace ZM\Exception; namespace ZM\Exception;
use Exception;
class NotInitializedException extends ZMException class NotInitializedException extends ZMException
{ {

View File

@ -4,7 +4,6 @@
namespace ZM\Exception; namespace ZM\Exception;
use Exception;
use Throwable; use Throwable;
/** /**

View File

@ -4,7 +4,6 @@
namespace ZM\Exception; namespace ZM\Exception;
use Exception;
use Throwable; use Throwable;
class WaitTimeoutException extends ZMException class WaitTimeoutException extends ZMException

View File

@ -6,7 +6,7 @@ namespace ZM;
use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\AnnotationReader;
use Exception; use Exception;
use ZM\Annotation\Swoole\ZMSetup; use ZM\Annotation\Swoole\OnSetup;
use ZM\Config\ZMConfig; use ZM\Config\ZMConfig;
use ZM\ConnectionManager\ManagerGM; use ZM\ConnectionManager\ManagerGM;
use ZM\Event\ServerEventHandler; use ZM\Event\ServerEventHandler;
@ -20,7 +20,7 @@ use ReflectionException;
use ReflectionMethod; use ReflectionMethod;
use Swoole\Runtime; use Swoole\Runtime;
use Swoole\WebSocket\Server; use Swoole\WebSocket\Server;
use ZM\Annotation\Swoole\HandleEvent; use ZM\Annotation\Swoole\SwooleHandler;
use ZM\Console\Console; use ZM\Console\Console;
use ZM\Utils\ZMUtil; use ZM\Utils\ZMUtil;
@ -67,7 +67,7 @@ class Framework
self::$server = new Server(ZMConfig::get("global", "host"), ZMConfig::get("global", "port")); self::$server = new Server(ZMConfig::get("global", "host"), ZMConfig::get("global", "port"));
$this->server_set = ZMConfig::get("global", "swoole"); $this->server_set = ZMConfig::get("global", "swoole");
Console::init( Console::init(
ZMConfig::get("global", "info_level"), ZMConfig::get("global", "info_level") ?? 2,
self::$server, self::$server,
$args["log-theme"] ?? "default", $args["log-theme"] ?? "default",
($o = ZMConfig::get("console_color")) === false ? [] : $o ($o = ZMConfig::get("console_color")) === false ? [] : $o
@ -150,11 +150,11 @@ class Framework
$method_annotations = $reader->getMethodAnnotations($vs); $method_annotations = $reader->getMethodAnnotations($vs);
if ($method_annotations != []) { if ($method_annotations != []) {
$annotation = $method_annotations[0]; $annotation = $method_annotations[0];
if ($annotation instanceof HandleEvent) { if ($annotation instanceof SwooleHandler) {
$annotation->class = $v; $annotation->class = $v;
$annotation->method = $vs->getName(); $annotation->method = $vs->getName();
$event_list[strtolower($annotation->event)] = $annotation; $event_list[strtolower($annotation->event)] = $annotation;
} elseif ($annotation instanceof ZMSetup) { } elseif ($annotation instanceof OnSetup) {
$annotation->class = $v; $annotation->class = $v;
$annotation->method = $vs->getName(); $annotation->method = $vs->getName();
$c = new $v(); $c = new $v();

View File

@ -4,6 +4,8 @@
namespace ZM\Http; namespace ZM\Http;
use ZM\Console\Console;
class Response class Response
{ {
@ -92,6 +94,7 @@ class Response
*/ */
public function status($http_code, $reason = null) { public function status($http_code, $reason = null) {
$this->status_code = $http_code; $this->status_code = $http_code;
Console::trace();
return $this->response->status($http_code, $reason); return $this->response->status($http_code, $reason);
} }
@ -184,7 +187,8 @@ class Response
* @return mixed * @return mixed
*/ */
public function redirect($location, $http_code = null) { public function redirect($location, $http_code = null) {
return $this->redirect($location, $http_code); $this->is_end = true;
return $this->response->redirect($location, $http_code);
} }
/** /**

View File

@ -21,7 +21,6 @@ use ZM\Utils\CoMessage;
/** /**
* Class QQBot * Class QQBot
* @package ZM\Module * @package ZM\Module
* @ExternalModule("onebot")
*/ */
class QQBot class QQBot
{ {
@ -80,12 +79,13 @@ class QQBot
//分发CQCommand事件 //分发CQCommand事件
$dispatcher = new EventDispatcher(CQCommand::class); $dispatcher = new EventDispatcher(CQCommand::class);
$dispatcher->setRuleFunction(function (CQCommand $v) use ($word) { $dispatcher->setRuleFunction(function (CQCommand $v) use ($word) {
if ($v->match == "" && $v->pattern == "" && $v->regex == "") return false; if(array_diff([$v->match, $v->pattern, $v->regex, $v->keyword, $v->end_with, $v->start_with], [""]) == []) return false;
elseif (($v->user_id == 0 || ($v->user_id != 0 && $v->user_id == ctx()->getUserId())) && elseif (($v->user_id == 0 || ($v->user_id != 0 && $v->user_id == ctx()->getUserId())) &&
($v->group_id == 0 || ($v->group_id != 0 && $v->group_id == (ctx()->getGroupId() ?? 0))) && ($v->group_id == 0 || ($v->group_id != 0 && $v->group_id == (ctx()->getGroupId() ?? 0))) &&
($v->message_type == '' || ($v->message_type != '' && $v->message_type == ctx()->getMessageType())) ($v->message_type == '' || ($v->message_type != '' && $v->message_type == ctx()->getMessageType()))
) { ) {
if(($word[0] != "" && $v->match == $word[0]) || in_array($word[0], $v->alias)) { if(($word[0] != "" && $v->match == $word[0]) || in_array($word[0], $v->alias)) {
array_shift($word);
ctx()->setCache("match", $word); ctx()->setCache("match", $word);
return true; return true;
} elseif ($v->start_with != "" && mb_strpos(ctx()->getMessage(), $v->start_with) === 0) { } elseif ($v->start_with != "" && mb_strpos(ctx()->getMessage(), $v->start_with) === 0) {
@ -94,6 +94,9 @@ class QQBot
} elseif ($v->end_with != "" && strlen(ctx()->getMessage()) == (strripos(ctx()->getMessage(), $v->end_with) + strlen($v->end_with))) { } elseif ($v->end_with != "" && strlen(ctx()->getMessage()) == (strripos(ctx()->getMessage(), $v->end_with) + strlen($v->end_with))) {
ctx()->setCache("match", [substr(ctx()->getMessage(), 0, strripos(ctx()->getMessage(), $v->end_with))]); ctx()->setCache("match", [substr(ctx()->getMessage(), 0, strripos(ctx()->getMessage(), $v->end_with))]);
return true; return true;
} elseif ($v->keyword != "" && mb_strpos(ctx()->getMessage(), $v->keyword) !== false) {
ctx()->setCache("match", explode($v->keyword, ctx()->getMessage()));
return true;
}elseif ($v->pattern != "") { }elseif ($v->pattern != "") {
$match = matchArgs($v->pattern, ctx()->getMessage()); $match = matchArgs($v->pattern, ctx()->getMessage());
if($match !== false) { if($match !== false) {

View File

@ -92,7 +92,7 @@ class LightCache
} elseif (is_bool($value)) { } elseif (is_bool($value)) {
$data_type = "bool"; $data_type = "bool";
$value = json_encode($value); $value = json_encode($value);
}else { } else {
throw new Exception("Only can set string, array and int"); throw new Exception("Only can set string, array and int");
} }
try { try {
@ -126,7 +126,7 @@ class LightCache
throw new Exception("Only can set string, array and int"); throw new Exception("Only can set string, array and int");
} }
try { try {
if(self::$kv_table->get($key) === false) return false; if (self::$kv_table->get($key) === false) return false;
return self::$kv_table->set($key, [ return self::$kv_table->set($key, [
"value" => $value, "value" => $value,
"data_type" => $data_type "data_type" => $data_type
@ -170,7 +170,7 @@ class LightCache
} }
public static function savePersistence() { public static function savePersistence() {
if(self::$kv_table === null) return; if (self::$kv_table === null) return;
$r = []; $r = [];
foreach (self::$kv_table as $k => $v) { foreach (self::$kv_table as $k => $v) {
if ($v["expire"] === -2) { if ($v["expire"] === -2) {
@ -179,8 +179,10 @@ class LightCache
} }
} }
if(self::$config["persistence_path"] == "") return; if(self::$config["persistence_path"] == "") return;
$r = file_put_contents(self::$config["persistence_path"], json_encode($r, 128 | 256)); if (file_exists(self::$config["persistence_path"])) {
if ($r === false) Console::error("Not saved, please check your \"persistence_path\"!"); $r = file_put_contents(self::$config["persistence_path"], json_encode($r, 128 | 256));
if ($r === false) Console::error("Not saved, please check your \"persistence_path\"!");
}
} }
private static function checkExpire($key) { private static function checkExpire($key) {

View File

@ -6,6 +6,7 @@ namespace ZM\Store;
use Exception; use Exception;
use Swoole\Table; use Swoole\Table;
use ZM\Exception\ZMException;
class LightCacheInside class LightCacheInside
{ {
@ -15,9 +16,11 @@ class LightCacheInside
public static $last_error = ''; public static $last_error = '';
public static function init() { public static function init() {
self::$kv_table["wait_api"] = new Table(2, 0); self::$kv_table["wait_api"] = new Table(3, 0);
self::$kv_table["wait_api"]->column("value", Table::TYPE_STRING, 65536); self::$kv_table["wait_api"]->column("value", Table::TYPE_STRING, 65536);
$result = self::$kv_table["wait_api"]->create(); self::$kv_table["connect"] = new Table(8, 0);
self::$kv_table["connect"]->column("value", Table::TYPE_STRING, 256);
$result = self::$kv_table["wait_api"]->create() && self::$kv_table["connect"]->create();
if ($result === false) { if ($result === false) {
self::$last_error = '系统内存不足,申请失败'; self::$last_error = '系统内存不足,申请失败';
return $result; return $result;
@ -25,8 +28,14 @@ class LightCacheInside
return $result; return $result;
} }
/**
* @param string $table
* @param string $key
* @return mixed|null
* @throws ZMException
*/
public static function get(string $table, string $key) { public static function get(string $table, string $key) {
if (!isset(self::$kv_table[$table])) throw new Exception("not initialized LightCache"); if (!isset(self::$kv_table[$table])) throw new ZMException("not initialized LightCache");
$r = self::$kv_table[$table]->get($key); $r = self::$kv_table[$table]->get($key);
return $r === false ? null : json_decode($r["value"], true); return $r === false ? null : json_decode($r["value"], true);
} }
@ -36,10 +45,10 @@ class LightCacheInside
* @param string $key * @param string $key
* @param string|array|int $value * @param string|array|int $value
* @return mixed * @return mixed
* @throws Exception * @throws ZMException
*/ */
public static function set(string $table, string $key, $value) { public static function set(string $table, string $key, $value) {
if (self::$kv_table === null) throw new Exception("not initialized LightCache"); if (self::$kv_table === null) throw new ZMException("not initialized LightCache");
try { try {
return self::$kv_table[$table]->set($key, [ return self::$kv_table[$table]->set($key, [
"value" => json_encode($value, 256) "value" => json_encode($value, 256)

View File

@ -29,6 +29,7 @@ class ZMAtomic
} }
self::$atomics["stop_signal"] = new Atomic(0); self::$atomics["stop_signal"] = new Atomic(0);
self::$atomics["wait_msg_id"] = new Atomic(0); self::$atomics["wait_msg_id"] = new Atomic(0);
self::$atomics["_event_id"] = new Atomic(0);
for ($i = 0; $i < 10; ++$i) { for ($i = 0; $i < 10; ++$i) {
self::$atomics["_tmp_" . $i] = new Atomic(0); self::$atomics["_tmp_" . $i] = new Atomic(0);
} }

View File

@ -0,0 +1,24 @@
<?php
namespace ZM\Utils;
trait SingletonTrait
{
/**
* @var self
*/
private static $instance;
/**
* @return self
*/
public static function getInstance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
}

View File

@ -37,9 +37,6 @@ class ZMUtil
if (($v["result"] ?? false) === null && isset($v["coroutine"])) Co::resume($v["coroutine"]); if (($v["result"] ?? false) === null && isset($v["coroutine"])) Co::resume($v["coroutine"]);
} }
LightCacheInside::unset("wait_api", "wait_api"); LightCacheInside::unset("wait_api", "wait_api");
foreach (server()->connections as $v) {
server()->close($v);
}
LightCache::savePersistence(); LightCache::savePersistence();
//DataProvider::saveBuffer(); //DataProvider::saveBuffer();
Timer::clearAll(); Timer::clearAll();

View File

@ -1,16 +1,20 @@
<?php <?php
use Swoole\Coroutine; use Swoole\Coroutine;
use ZM\API\ZMRobot;
use ZM\Config\ZMConfig; use ZM\Config\ZMConfig;
use ZM\ConnectionManager\ManagerGM;
use ZM\Console\Console; use ZM\Console\Console;
use ZM\Context\Context; use ZM\Context\Context;
use ZM\Event\EventManager; use ZM\Event\EventManager;
use ZM\Exception\RobotNotFoundException;
use ZM\Exception\ZMException;
use ZM\Framework; use ZM\Framework;
use ZM\Store\LightCacheInside;
use ZM\Store\ZMBuf; use ZM\Store\ZMBuf;
use ZM\Utils\DataProvider; use ZM\Utils\DataProvider;
use Swoole\Coroutine\System; use Swoole\Coroutine\System;
use ZM\Context\ContextInterface; use ZM\Context\ContextInterface;
use ZM\Utils\ZMUtil;
function phar_classloader($p) { function phar_classloader($p) {
@ -181,11 +185,11 @@ function getAnnotations() {
$s = debug_backtrace()[1]; $s = debug_backtrace()[1];
//echo json_encode($s, 128|256); //echo json_encode($s, 128|256);
$list = []; $list = [];
foreach(EventManager::$events as $event => $v) { foreach (EventManager::$events as $event => $v) {
foreach($v as $ks => $vs) { foreach ($v as $ks => $vs) {
//echo get_class($vs).": ".$vs->class." => ".$vs->method.PHP_EOL; //echo get_class($vs).": ".$vs->class." => ".$vs->method.PHP_EOL;
if($vs->class == $s["class"] && $vs->method == $s["function"]) { if ($vs->class == $s["class"] && $vs->method == $s["function"]) {
$list[get_class($vs)][]=$vs; $list[get_class($vs)][] = $vs;
} }
} }
} }
@ -227,7 +231,7 @@ function ctx() {
} }
} }
function debug($msg) { Console::debug($msg); } function zm_debug($msg) { Console::debug($msg); }
function onebot_target_id_name($message_type) { function onebot_target_id_name($message_type) {
return ($message_type == "group" ? "group_id" : "user_id"); return ($message_type == "group" ? "group_id" : "user_id");
@ -268,6 +272,22 @@ function server() {
return Framework::$server; return Framework::$server;
} }
/**
* @return ZMRobot
* @throws RobotNotFoundException
* @throws ZMException
*/
function bot() {
if (($conn = LightCacheInside::get("connect", "conn_fd")) == -2) {
return ZMRobot::getRandom();
} elseif ($conn != -1) {
if (($obj = ManagerGM::get($conn)) !== null) return new ZMRobot($obj);
else throw new RobotNotFoundException("单机器人连接模式可能连接了多个机器人!");
} else {
throw new RobotNotFoundException("没有任何机器人连接到框架!");
}
}

View File

@ -9,7 +9,7 @@ use Module\Example\Hello;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use ReflectionException; use ReflectionException;
use ZM\Annotation\AnnotationParser; use ZM\Annotation\AnnotationParser;
use ZM\Annotation\Swoole\OnWorkerStart; use ZM\Annotation\Swoole\OnStart;
use ZM\Console\Console; use ZM\Console\Console;
class AnnotationParserRegisterTest extends TestCase class AnnotationParserRegisterTest extends TestCase
@ -34,8 +34,8 @@ class AnnotationParserRegisterTest extends TestCase
public function testAnnotation() { public function testAnnotation() {
ob_start(); ob_start();
$gen = $this->parser->generateAnnotationEvents(); $gen = $this->parser->generateAnnotationEvents();
$m = $gen[OnWorkerStart::class][0]->method; $m = $gen[OnStart::class][0]->method;
$class = $gen[OnWorkerStart::class][0]->class; $class = $gen[OnStart::class][0]->class;
$c = new $class(); $c = new $class();
try { try {
$c->$m(); $c->$m();