2022-03-15 18:05:33 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
2021-03-18 14:56:35 +08:00
|
|
|
|
use Swoole\Atomic;
|
2020-11-03 21:02:24 +08:00
|
|
|
|
use Swoole\Coroutine;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
use Swoole\Coroutine as Co;
|
|
|
|
|
|
use Swoole\Coroutine\System;
|
2021-03-18 14:56:35 +08:00
|
|
|
|
use Swoole\WebSocket\Server;
|
2021-03-24 23:34:46 +08:00
|
|
|
|
use Symfony\Component\VarDumper\VarDumper;
|
2021-06-16 00:17:30 +08:00
|
|
|
|
use ZM\API\OneBotV11;
|
2022-03-21 20:08:09 +08:00
|
|
|
|
use ZM\API\ZMRobot;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use ZM\Config\ZMConfig;
|
2020-12-14 01:24:34 +08:00
|
|
|
|
use ZM\ConnectionManager\ManagerGM;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use ZM\Console\Console;
|
2022-04-05 00:24:03 +08:00
|
|
|
|
use ZM\Container\Container;
|
|
|
|
|
|
use ZM\Container\ContainerInterface;
|
2020-09-29 15:07:43 +08:00
|
|
|
|
use ZM\Context\Context;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
use ZM\Context\ContextInterface;
|
2020-09-29 15:07:43 +08:00
|
|
|
|
use ZM\Event\EventManager;
|
2020-12-14 01:24:34 +08:00
|
|
|
|
use ZM\Exception\RobotNotFoundException;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use ZM\Framework;
|
2020-12-14 01:24:34 +08:00
|
|
|
|
use ZM\Store\LightCacheInside;
|
2021-03-18 14:56:35 +08:00
|
|
|
|
use ZM\Store\ZMAtomic;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use ZM\Store\ZMBuf;
|
|
|
|
|
|
use ZM\Utils\DataProvider;
|
2020-05-02 23:27:26 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取类路径
|
|
|
|
|
|
*/
|
|
|
|
|
|
function get_class_path(string $class_name): ?string
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$dir = str_replace('\\', '/', $class_name);
|
2022-03-21 20:08:09 +08:00
|
|
|
|
$dir = DataProvider::getSourceRootDir() . '/src/' . $dir . '.php';
|
|
|
|
|
|
$dir = str_replace('\\', '/', $dir);
|
|
|
|
|
|
if (file_exists($dir)) {
|
|
|
|
|
|
return $dir;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
return null;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
2022-03-13 22:47:11 +08:00
|
|
|
|
|
2021-11-02 16:01:24 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 检查炸毛框架运行的环境
|
2022-04-05 00:24:03 +08:00
|
|
|
|
*
|
2021-11-02 16:01:24 +08:00
|
|
|
|
* @internal
|
|
|
|
|
|
*/
|
2022-03-13 22:47:11 +08:00
|
|
|
|
function _zm_env_check()
|
|
|
|
|
|
{
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (!extension_loaded('swoole')) {
|
|
|
|
|
|
exit(zm_internal_errcode('E00001') . "Can not find swoole extension.\n");
|
|
|
|
|
|
}
|
2022-03-21 20:08:09 +08:00
|
|
|
|
if (version_compare(SWOOLE_VERSION, '4.5.0') === -1) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
exit(zm_internal_errcode('E00002') . 'You must install swoole version >= 4.5.0 !');
|
|
|
|
|
|
}
|
2022-03-21 20:08:09 +08:00
|
|
|
|
if (version_compare(PHP_VERSION, '7.2') === -1) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
exit(zm_internal_errcode('E00003') . 'PHP >= 7.2 required.');
|
|
|
|
|
|
}
|
|
|
|
|
|
if (version_compare(SWOOLE_VERSION, '4.6.7') < 0 && !extension_loaded('pcntl')) {
|
|
|
|
|
|
Console::error(zm_internal_errcode('E00004') . 'Swoole 版本必须不低于 4.6.7 或 PHP 安装加载了 pcntl 扩展!');
|
|
|
|
|
|
exit();
|
2021-11-02 16:01:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-03-02 16:14:20 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2022-03-21 20:08:09 +08:00
|
|
|
|
* 分割消息字符串
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param array $includes 需要进行切割的字符串,默认包含空格及制表符(\t)
|
2020-03-02 16:14:20 +08:00
|
|
|
|
*/
|
2022-03-21 20:08:09 +08:00
|
|
|
|
function explode_msg(string $msg, array $includes = [' ', "\t"]): array
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-03-21 20:08:09 +08:00
|
|
|
|
$msg = trim($msg);
|
|
|
|
|
|
foreach ($includes as $v) {
|
|
|
|
|
|
$msg = str_replace($v, "\n", $msg);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
2022-03-21 20:08:09 +08:00
|
|
|
|
$msg_seg = explode("\n", $msg);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
$ls = [];
|
2022-03-21 20:08:09 +08:00
|
|
|
|
foreach ($msg_seg as $v) {
|
|
|
|
|
|
if (empty(trim($v))) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
}
|
2020-03-02 16:14:20 +08:00
|
|
|
|
$ls[] = trim($v);
|
|
|
|
|
|
}
|
|
|
|
|
|
return $ls;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 解码Unicode字符串
|
|
|
|
|
|
*/
|
|
|
|
|
|
function unicode_decode(string $str): ?string
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-03-21 20:08:09 +08:00
|
|
|
|
return preg_replace_callback('/\\\\u([0-9a-f]{4})/i', static function ($matches) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UCS-2BE');
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}, $str);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 格式匹配
|
|
|
|
|
|
*/
|
|
|
|
|
|
function match_pattern(string $pattern, string $subject): bool
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-04-28 21:50:48 +08:00
|
|
|
|
$pattern = str_replace(['\*', '\\\\.*'], ['.*', '\*'], preg_quote($pattern, '/'));
|
|
|
|
|
|
$pattern = '/^' . $pattern . '$/i';
|
|
|
|
|
|
return preg_match($pattern, $subject) === 1;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-02 23:37:22 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @requires symfony/polyfill-ctype
|
|
|
|
|
|
* @return array|string[]
|
|
|
|
|
|
*/
|
2022-03-21 20:08:09 +08:00
|
|
|
|
function split_explode(string $del, string $string, bool $divide_en = false): array
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-03-21 20:08:09 +08:00
|
|
|
|
$str = explode($del, $string);
|
|
|
|
|
|
for ($i = 0, $i_max = mb_strlen($str[0]); $i < $i_max; ++$i) {
|
2020-03-02 16:14:20 +08:00
|
|
|
|
if (
|
2022-03-15 18:05:33 +08:00
|
|
|
|
is_numeric(mb_substr($str[0], $i, 1))
|
|
|
|
|
|
&& (
|
|
|
|
|
|
!is_numeric(mb_substr($str[0], $i - 1, 1))
|
2022-03-21 20:08:09 +08:00
|
|
|
|
&& mb_substr($str[0], $i - 1, 1) !== ' '
|
2022-03-15 18:05:33 +08:00
|
|
|
|
&& ctype_alpha(mb_substr($str[0], $i - 1, 1)) === false
|
2020-03-02 16:14:20 +08:00
|
|
|
|
)
|
|
|
|
|
|
) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$str[0] = mb_substr($str[0], 0, $i) . ' ' . mb_substr($str[0], $i);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
} elseif (
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$divide_en
|
2022-03-21 20:08:09 +08:00
|
|
|
|
&& mb_substr($str[0], $i - 1, 1) !== ' '
|
2022-03-15 18:05:33 +08:00
|
|
|
|
&& ctype_alnum(mb_substr($str[0], $i, 1))
|
|
|
|
|
|
&& !ctype_alnum(mb_substr($str[0], $i - 1, 1))
|
2020-03-02 16:14:20 +08:00
|
|
|
|
) {
|
|
|
|
|
|
$str[0] = mb_substr($str[0], 0, $i) . ' ' . mb_substr($str[0], $i);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
$str = implode($del, $str);
|
2022-03-21 20:08:09 +08:00
|
|
|
|
|
2020-03-02 16:14:20 +08:00
|
|
|
|
$ls = [];
|
2021-06-16 00:17:30 +08:00
|
|
|
|
foreach (explode($del, $str) as $v) {
|
2022-03-21 20:08:09 +08:00
|
|
|
|
if (empty(trim($v))) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
}
|
2020-03-02 16:14:20 +08:00
|
|
|
|
$ls[] = $v;
|
|
|
|
|
|
}
|
2022-03-21 20:08:09 +08:00
|
|
|
|
return $ls ?: [''];
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 匹配参数
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return array|false 成功时返回匹配到的参数数组,失败时返回false
|
|
|
|
|
|
*/
|
|
|
|
|
|
function match_args(string $pattern, string $subject)
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2020-03-02 16:14:20 +08:00
|
|
|
|
$result = [];
|
2022-03-21 20:08:09 +08:00
|
|
|
|
if (match_pattern($pattern, $subject)) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (mb_strpos($pattern, '*') === false) {
|
|
|
|
|
|
return [];
|
|
|
|
|
|
}
|
|
|
|
|
|
$exp = explode('*', $pattern);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
$i = 0;
|
|
|
|
|
|
foreach ($exp as $k => $v) {
|
2022-03-21 20:08:09 +08:00
|
|
|
|
if (empty($v) && $k === 0) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
continue;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
2022-03-21 20:08:09 +08:00
|
|
|
|
if (empty($v) && $k === count($exp) - 1) {
|
|
|
|
|
|
$subject .= '^EOL';
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$v = '^EOL';
|
|
|
|
|
|
}
|
|
|
|
|
|
$cur_var = '';
|
2020-03-02 16:14:20 +08:00
|
|
|
|
$ori = $i;
|
2022-03-21 20:08:09 +08:00
|
|
|
|
while (($a = mb_substr($subject, $i, mb_strlen($v))) !== $v && !empty($a)) {
|
|
|
|
|
|
$cur_var .= mb_substr($subject, $i, 1);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
++$i;
|
|
|
|
|
|
}
|
2022-03-21 20:08:09 +08:00
|
|
|
|
if ($i !== $ori || $k === 1 || $k === count($exp) - 1) {
|
2020-03-02 16:14:20 +08:00
|
|
|
|
$result[] = $cur_var;
|
|
|
|
|
|
}
|
|
|
|
|
|
$i += mb_strlen($v);
|
|
|
|
|
|
}
|
|
|
|
|
|
return $result;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
return false;
|
2020-03-29 16:29:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 判断当前连接类型是否为传入的$type
|
|
|
|
|
|
*
|
2022-05-04 21:05:10 +08:00
|
|
|
|
* @param string $type 连接类型
|
2022-03-21 20:08:09 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function current_connection_is(string $type): bool
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-03-21 20:08:09 +08:00
|
|
|
|
return ctx()->getConnection()->getName() === $type;
|
2020-09-29 15:07:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取触发当前方法的注解
|
|
|
|
|
|
*/
|
|
|
|
|
|
function get_annotations(): array
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$s = debug_backtrace()[1];
|
|
|
|
|
|
$list = [];
|
2021-06-16 00:17:30 +08:00
|
|
|
|
foreach (EventManager::$events as $v) {
|
|
|
|
|
|
foreach ($v as $vs) {
|
2022-03-21 20:08:09 +08:00
|
|
|
|
if ($vs->class === $s['class'] && $vs->method === $s['function']) {
|
2020-12-14 01:24:34 +08:00
|
|
|
|
$list[get_class($vs)][] = $vs;
|
2020-09-29 15:07:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return $list;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 设置协程参数
|
|
|
|
|
|
*/
|
|
|
|
|
|
function set_coroutine_params(array $params): void
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-04-10 00:58:07 +08:00
|
|
|
|
$cid = co::getCid();
|
2022-03-21 20:08:09 +08:00
|
|
|
|
if ($cid === -1) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
exit(zm_internal_errcode('E00061') . 'Cannot set coroutine params at none coroutine mode.');
|
|
|
|
|
|
}
|
|
|
|
|
|
if (isset(Context::$context[$cid])) {
|
2022-03-21 20:08:09 +08:00
|
|
|
|
Context::$context[$cid] = array_merge(Context::$context[$cid], $params);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
} else {
|
2022-03-21 20:08:09 +08:00
|
|
|
|
Context::$context[$cid] = $params;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
}
|
2020-09-29 15:07:43 +08:00
|
|
|
|
foreach (Context::$context as $c => $v) {
|
2022-04-10 00:58:07 +08:00
|
|
|
|
if (!co::exists($c)) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
unset(Context::$context[$c], ZMBuf::$context_class[$c]);
|
|
|
|
|
|
}
|
2020-03-29 16:29:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-17 19:42:59 +08:00
|
|
|
|
/**
|
2022-03-21 20:08:09 +08:00
|
|
|
|
* 获取当前上下文
|
2022-03-17 19:42:59 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function context(): ContextInterface
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2020-05-23 17:23:29 +08:00
|
|
|
|
return ctx();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-17 19:42:59 +08:00
|
|
|
|
/**
|
2022-03-21 20:08:09 +08:00
|
|
|
|
* 获取当前上下文
|
2022-03-17 19:42:59 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function ctx(): ContextInterface
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-04-10 00:58:07 +08:00
|
|
|
|
$cid = co::getCid();
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$c_class = ZMConfig::get('global', 'context_class');
|
2020-09-29 15:07:43 +08:00
|
|
|
|
if (isset(Context::$context[$cid])) {
|
2020-05-23 17:23:29 +08:00
|
|
|
|
return ZMBuf::$context_class[$cid] ?? (ZMBuf::$context_class[$cid] = new $c_class($cid));
|
2020-04-14 23:46:42 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
Console::debug("未找到当前协程的上下文({$cid}),正在找父进程的上下文");
|
2022-04-10 00:58:07 +08:00
|
|
|
|
while (($parent_cid = co::getPcid($cid)) !== -1) {
|
2022-03-21 20:08:09 +08:00
|
|
|
|
$cid = $parent_cid;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (isset(Context::$context[$cid])) {
|
|
|
|
|
|
return ZMBuf::$context_class[$cid] ?? (ZMBuf::$context_class[$cid] = new $c_class($cid));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-04-30 13:38:15 +08:00
|
|
|
|
Console::warning('当前环境不是协程环境,将返回独立的非协程的容器');
|
|
|
|
|
|
return ZMBuf::$context_class[$cid] ?? (ZMBuf::$context_class[$cid] = new $c_class($cid));
|
2020-04-14 23:46:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 根据消息类型获取对应的OneBot目标名称
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return string 如传入的消息类型不被支持,将默认返回`user_id`
|
|
|
|
|
|
*/
|
|
|
|
|
|
function get_onebot_target_id_name(string $message_type): string
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-03-21 20:08:09 +08:00
|
|
|
|
switch ($message_type) {
|
|
|
|
|
|
case 'group':
|
|
|
|
|
|
return 'group_id';
|
|
|
|
|
|
case 'discuss':
|
|
|
|
|
|
return 'discuss_id';
|
|
|
|
|
|
case 'private':
|
|
|
|
|
|
default:
|
|
|
|
|
|
return 'user_id';
|
2022-03-15 18:05:33 +08:00
|
|
|
|
}
|
2020-11-03 21:02:24 +08:00
|
|
|
|
}
|
2020-05-23 17:23:29 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 协程休眠
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link sleep()} 一致,只是增加了协程支持
|
|
|
|
|
|
*
|
|
|
|
|
|
* @since 2.7.3 此函数不再返回 true
|
|
|
|
|
|
*/
|
|
|
|
|
|
function zm_sleep(int $seconds = 1): void
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-03-21 20:08:09 +08:00
|
|
|
|
if (Coroutine::getCid() !== -1) {
|
|
|
|
|
|
System::sleep($seconds);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
usleep($seconds * 1000 * 1000);
|
|
|
|
|
|
}
|
2021-03-24 23:34:46 +08:00
|
|
|
|
}
|
2020-05-23 17:23:29 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 协程执行命令
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link exec()} 一致,只是增加了协程支持
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return array{code: int, signal: int, output: string}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function zm_exec(string $command): array
|
|
|
|
|
|
{
|
|
|
|
|
|
return System::exec($command);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取当前协程ID
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link Co::getCid()} 一致
|
|
|
|
|
|
*/
|
|
|
|
|
|
function zm_cid(): int
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-04-10 00:58:07 +08:00
|
|
|
|
return co::getCid();
|
2021-03-24 23:34:46 +08:00
|
|
|
|
}
|
2020-05-23 17:23:29 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 挂起当前协程
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link Co::yield()} 一致
|
|
|
|
|
|
*/
|
2022-03-13 22:47:11 +08:00
|
|
|
|
function zm_yield()
|
|
|
|
|
|
{
|
2022-04-10 00:58:07 +08:00
|
|
|
|
co::yield();
|
2021-03-24 23:34:46 +08:00
|
|
|
|
}
|
2020-05-23 17:23:29 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 恢复并继续执行指定协程
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link Co::resume()} 一致
|
|
|
|
|
|
*/
|
2022-03-13 22:47:11 +08:00
|
|
|
|
function zm_resume(int $cid)
|
|
|
|
|
|
{
|
2022-04-10 00:58:07 +08:00
|
|
|
|
co::resume($cid);
|
2021-03-24 23:34:46 +08:00
|
|
|
|
}
|
2020-05-23 17:23:29 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 指定延迟后执行函数
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param int $delay 延迟时间,单位毫秒ms
|
|
|
|
|
|
*/
|
2022-03-21 23:28:57 +08:00
|
|
|
|
function zm_timer_after(int $delay, callable $runnable)
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-03-21 20:08:09 +08:00
|
|
|
|
Swoole\Timer::after($delay, static function () use ($runnable) {
|
|
|
|
|
|
call_with_catch($runnable);
|
2020-05-23 17:23:29 +08:00
|
|
|
|
});
|
2020-03-29 16:29:02 +08:00
|
|
|
|
}
|
2020-05-23 17:23:29 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 重复在指定时间间隔后执行函数
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param int $interval 间隔时间,单位毫秒ms
|
|
|
|
|
|
* @return false|int 定时器ID,失败返回false
|
|
|
|
|
|
*/
|
2022-03-21 23:28:57 +08:00
|
|
|
|
function zm_timer_tick(int $interval, callable $runnable)
|
2022-03-21 20:08:09 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (zm_cid() === -1) {
|
|
|
|
|
|
return go(static function () use ($interval, $runnable) {
|
|
|
|
|
|
Console::debug('Adding extra timer tick of ' . $interval . ' ms');
|
|
|
|
|
|
Swoole\Timer::tick($interval, static function () use ($runnable) {
|
|
|
|
|
|
call_with_catch($runnable);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return Swoole\Timer::tick($interval, static function () use ($runnable) {
|
|
|
|
|
|
call_with_catch($runnable);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 执行函数并记录异常
|
|
|
|
|
|
*/
|
|
|
|
|
|
function call_with_catch(callable $callable): void
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2021-03-13 15:16:10 +08:00
|
|
|
|
try {
|
|
|
|
|
|
$callable();
|
|
|
|
|
|
} catch (Exception $e) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
|
|
|
|
|
|
Console::error(zm_internal_errcode('E00033') . 'Uncaught exception ' . get_class($e) . ': ' . $error_msg);
|
2021-03-13 15:16:10 +08:00
|
|
|
|
Console::trace();
|
|
|
|
|
|
} catch (Error $e) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
|
|
|
|
|
|
Console::error(zm_internal_errcode('E00033') . 'Uncaught ' . get_class($e) . ': ' . $error_msg);
|
2021-03-13 15:16:10 +08:00
|
|
|
|
Console::trace();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 生成消息的哈希值
|
|
|
|
|
|
*/
|
|
|
|
|
|
function hash_message(array $message): string
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-03-21 20:08:09 +08:00
|
|
|
|
return md5($message['user_id'] . '^' . $message['self_id'] . '^' . $message['message_type'] . '^' . ($message[$message['message_type'] . '_id'] ?? $message['user_id']));
|
2020-09-29 15:07:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取 Swoole Server 实例
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link Framework::$server} 一致
|
|
|
|
|
|
*/
|
2022-04-03 01:47:38 +08:00
|
|
|
|
function server(): Server
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2020-09-29 15:07:43 +08:00
|
|
|
|
return Framework::$server;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-13 22:47:11 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取缓存当前框架pid的临时目录
|
2022-04-05 00:24:03 +08:00
|
|
|
|
*
|
2022-03-21 20:08:09 +08:00
|
|
|
|
* @internal
|
2022-03-13 22:47:11 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function _zm_pid_dir(): string
|
|
|
|
|
|
{
|
|
|
|
|
|
global $_ZM_HASH;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (!isset($_ZM_HASH)) {
|
|
|
|
|
|
$_ZM_HASH = md5(DataProvider::getWorkingDir());
|
|
|
|
|
|
}
|
2022-03-13 22:47:11 +08:00
|
|
|
|
return '/tmp/.zm_' . $_ZM_HASH;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-12-14 01:24:34 +08:00
|
|
|
|
/**
|
2022-03-21 20:08:09 +08:00
|
|
|
|
* 获取 ZMRobot 实例
|
|
|
|
|
|
*
|
|
|
|
|
|
* 随机返回一个 ZMRobot 实例,效果等同于 {@link ZMRobot::getRandom()}。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 在单机器人模式下,会直接返回该机器人实例。
|
2022-04-05 00:24:03 +08:00
|
|
|
|
*
|
2020-12-14 01:24:34 +08:00
|
|
|
|
* @throws RobotNotFoundException
|
|
|
|
|
|
*/
|
2022-03-21 20:08:09 +08:00
|
|
|
|
function bot(): ZMRobot
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-03-21 20:08:09 +08:00
|
|
|
|
if (($conn = LightCacheInside::get('connect', 'conn_fd')) === -2) {
|
2021-06-16 00:17:30 +08:00
|
|
|
|
return OneBotV11::getRandom();
|
2020-12-14 01:24:34 +08:00
|
|
|
|
}
|
2022-03-21 20:08:09 +08:00
|
|
|
|
if ($conn !== -1) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (($obj = ManagerGM::get($conn)) !== null) {
|
2022-03-21 20:08:09 +08:00
|
|
|
|
return new ZMRobot($obj);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
throw new RobotNotFoundException('单机器人连接模式可能连接了多个机器人!');
|
|
|
|
|
|
}
|
|
|
|
|
|
throw new RobotNotFoundException('没有任何机器人连接到框架!');
|
2020-12-14 01:24:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-12-25 16:40:02 +08:00
|
|
|
|
/**
|
2022-03-21 20:08:09 +08:00
|
|
|
|
* 获取指定连接类型的文件描述符ID
|
2020-12-25 16:40:02 +08:00
|
|
|
|
*/
|
2022-03-21 20:08:09 +08:00
|
|
|
|
function get_all_fd_of_type(string $type = 'default'): array
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2020-12-25 16:40:02 +08:00
|
|
|
|
$fds = [];
|
|
|
|
|
|
foreach (ManagerGM::getAllByName($type) as $obj) {
|
2020-12-25 16:41:14 +08:00
|
|
|
|
$fds[] = $obj->getFd();
|
2020-12-25 15:48:41 +08:00
|
|
|
|
}
|
2020-12-25 16:40:02 +08:00
|
|
|
|
return $fds;
|
2020-12-25 15:48:41 +08:00
|
|
|
|
}
|
2021-02-07 11:46:42 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取原子计数器
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link ZMAtomic::get()} 一致
|
|
|
|
|
|
*/
|
|
|
|
|
|
function zm_atomic(string $name): ?Atomic
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2021-03-18 14:56:35 +08:00
|
|
|
|
return ZMAtomic::get($name);
|
2021-02-21 22:17:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 生成 UUID
|
|
|
|
|
|
*/
|
|
|
|
|
|
function uuidgen(bool $uppercase = false): string
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2021-02-21 22:17:34 +08:00
|
|
|
|
try {
|
|
|
|
|
|
$data = random_bytes(16);
|
|
|
|
|
|
} catch (Exception $e) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
return '';
|
2021-02-21 22:17:34 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$data[6] = chr(ord($data[6]) & 0x0F | 0x40);
|
|
|
|
|
|
$data[8] = chr(ord($data[8]) & 0x3F | 0x80);
|
2021-02-21 22:17:34 +08:00
|
|
|
|
return $uppercase ? strtoupper(vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4))) :
|
|
|
|
|
|
vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
|
2021-02-24 23:37:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取框架运行的工作目录
|
|
|
|
|
|
*
|
|
|
|
|
|
* @example 例如你是从 /root/framework-starter/ 目录启动的框架,vendor/bin/start server,那么 working_dir() 返回的就是 /root/framework-starter。
|
|
|
|
|
|
*/
|
|
|
|
|
|
function working_dir(): string
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2021-03-27 16:30:15 +08:00
|
|
|
|
return WORKING_DIR;
|
2021-02-24 23:37:00 +08:00
|
|
|
|
}
|
2021-03-24 23:34:46 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 更漂亮地输出变量值
|
|
|
|
|
|
*
|
|
|
|
|
|
* 可替代 {@link var_dump()}
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param mixed $var
|
|
|
|
|
|
* @return array|mixed 返回传入的变量,传入多个变量则会返回数组
|
|
|
|
|
|
*/
|
2022-03-13 22:47:11 +08:00
|
|
|
|
function zm_dump($var, ...$moreVars)
|
|
|
|
|
|
{
|
2021-03-24 23:34:46 +08:00
|
|
|
|
VarDumper::dump($var);
|
|
|
|
|
|
|
|
|
|
|
|
foreach ($moreVars as $v) {
|
|
|
|
|
|
VarDumper::dump($v);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
if (func_num_args() > 1) {
|
2021-03-24 23:34:46 +08:00
|
|
|
|
return func_get_args();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return $var;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 输出info日志
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link Console::info()} 一致
|
|
|
|
|
|
*
|
2022-04-02 23:37:22 +08:00
|
|
|
|
* @param mixed $obj
|
2022-03-21 20:08:09 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function zm_info($obj): void
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2021-11-02 16:01:24 +08:00
|
|
|
|
Console::info($obj);
|
|
|
|
|
|
}
|
2021-03-24 23:34:46 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 输出warning日志
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link Console::warning()} 一致
|
|
|
|
|
|
*
|
2022-04-02 23:37:22 +08:00
|
|
|
|
* @param mixed $obj
|
2022-03-21 20:08:09 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function zm_warning($obj): void
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2021-11-02 16:01:24 +08:00
|
|
|
|
Console::warning($obj);
|
|
|
|
|
|
}
|
2021-03-24 23:34:46 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 输出success日志
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link Console::success()} 一致
|
|
|
|
|
|
*
|
2022-04-02 23:37:22 +08:00
|
|
|
|
* @param mixed $obj
|
2022-03-21 20:08:09 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function zm_success($obj): void
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2021-11-02 16:01:24 +08:00
|
|
|
|
Console::success($obj);
|
|
|
|
|
|
}
|
2021-03-24 23:34:46 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 输出debug日志
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link Console::debug()} 一致
|
|
|
|
|
|
*
|
2022-04-02 23:37:22 +08:00
|
|
|
|
* @param mixed $obj
|
2022-03-21 20:08:09 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function zm_debug($obj): void
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2021-11-02 16:01:24 +08:00
|
|
|
|
Console::debug($obj);
|
|
|
|
|
|
}
|
2021-03-24 23:34:46 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 输出verbose日志
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link Console::verbose()} 一致
|
|
|
|
|
|
*
|
2022-04-02 23:37:22 +08:00
|
|
|
|
* @param mixed $obj
|
2022-03-21 20:08:09 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function zm_verbose($obj): void
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2021-11-02 16:01:24 +08:00
|
|
|
|
Console::verbose($obj);
|
|
|
|
|
|
}
|
2021-03-24 23:34:46 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 输出error日志
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link Console::error()} 一致
|
|
|
|
|
|
*
|
2022-04-02 23:37:22 +08:00
|
|
|
|
* @param mixed $obj
|
2022-03-21 20:08:09 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function zm_error($obj): void
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2021-11-02 16:01:24 +08:00
|
|
|
|
Console::error($obj);
|
|
|
|
|
|
}
|
2021-03-24 23:34:46 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取配置项
|
|
|
|
|
|
*
|
|
|
|
|
|
* 与 {@link ZMConfig::get()} 一致
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return mixed
|
|
|
|
|
|
*/
|
|
|
|
|
|
function zm_config(string $name, ?string $key = null)
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2021-11-02 16:01:24 +08:00
|
|
|
|
return ZMConfig::get($name, $key);
|
|
|
|
|
|
}
|
2021-03-25 16:18:09 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 生成快速回复闭包
|
|
|
|
|
|
*
|
2022-04-02 23:37:22 +08:00
|
|
|
|
* @param mixed $reply
|
2022-03-21 20:08:09 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function quick_reply_closure($reply): Closure
|
2022-03-13 22:47:11 +08:00
|
|
|
|
{
|
2022-03-21 20:08:09 +08:00
|
|
|
|
return static function () use ($reply) {
|
2021-03-25 16:18:09 +08:00
|
|
|
|
return $reply;
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2021-06-16 00:17:30 +08:00
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取内部错误码
|
|
|
|
|
|
*
|
2022-04-02 23:37:22 +08:00
|
|
|
|
* @param int|string $code
|
2022-03-21 20:08:09 +08:00
|
|
|
|
*/
|
2022-03-13 22:47:11 +08:00
|
|
|
|
function zm_internal_errcode($code): string
|
|
|
|
|
|
{
|
2022-03-15 18:05:33 +08:00
|
|
|
|
return "[ErrCode:{$code}] ";
|
2021-06-16 00:17:30 +08:00
|
|
|
|
}
|
2022-03-21 20:08:09 +08:00
|
|
|
|
|
2022-04-15 23:10:29 +08:00
|
|
|
|
if (!function_exists('chain')) {
|
|
|
|
|
|
define('CARRY', '{carry}');
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 链式调用对象方法
|
|
|
|
|
|
*
|
|
|
|
|
|
* 如需使用上一步的返回值作为参数,请使用 CARRY 常量替换对应的参数值
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param object $object 需要进行链式调用的对象
|
|
|
|
|
|
* @return object 链式操作对象,可当成传入的对象使用
|
|
|
|
|
|
*/
|
|
|
|
|
|
function chain(object $object): object
|
|
|
|
|
|
{
|
|
|
|
|
|
return new class($object) {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 最后一次执行的方法的返回值
|
|
|
|
|
|
*
|
|
|
|
|
|
* @var mixed
|
|
|
|
|
|
*/
|
|
|
|
|
|
protected $return;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 需要进行链式调用的对象
|
|
|
|
|
|
*
|
|
|
|
|
|
* @var object
|
|
|
|
|
|
*/
|
|
|
|
|
|
protected $wrapped;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 构造链式调用匿名类
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function __construct(object $object)
|
|
|
|
|
|
{
|
|
|
|
|
|
$this->wrapped = $object;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 代理所有调用
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function __call(string $name, array $arguments)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (($index = array_search(CARRY, $arguments, true)) !== false) {
|
|
|
|
|
|
$arguments[$index] = $this->return;
|
|
|
|
|
|
}
|
|
|
|
|
|
$this->return = $this->wrapped->{$name}(...$arguments);
|
|
|
|
|
|
return $this;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 返回最后执行结果
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function __toString()
|
|
|
|
|
|
{
|
|
|
|
|
|
return (string) $this->return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 允许调用最后返回结果
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function __invoke()
|
|
|
|
|
|
{
|
|
|
|
|
|
return $this->return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 使用链式操作对象作为参数,执行回调
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function tap(callable $callback): self
|
|
|
|
|
|
{
|
|
|
|
|
|
$callback($this->wrapped);
|
|
|
|
|
|
return $this;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!function_exists('stopwatch')) {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 执行回调函数并返回平均执行耗时
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param int $times 执行次数
|
|
|
|
|
|
* @return float 平均执行耗时
|
|
|
|
|
|
*/
|
|
|
|
|
|
function stopwatch(callable $callback, int $times = 1): float
|
|
|
|
|
|
{
|
|
|
|
|
|
$total = 0;
|
|
|
|
|
|
for ($i = 0; $i < $times; ++$i) {
|
|
|
|
|
|
$start = microtime(true);
|
|
|
|
|
|
$callback();
|
|
|
|
|
|
$total += microtime(true) - $start;
|
|
|
|
|
|
}
|
|
|
|
|
|
return $total / $times;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-04 00:10:42 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 将可能为数组的参数转换为字符串
|
|
|
|
|
|
*
|
|
|
|
|
|
* 如传入字符串则为原样返回
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param array|string $string_or_array
|
|
|
|
|
|
*/
|
|
|
|
|
|
function implode_when_necessary($string_or_array): string
|
|
|
|
|
|
{
|
|
|
|
|
|
return is_array($string_or_array) ? implode(', ', $string_or_array) : $string_or_array;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-05 00:24:03 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取容器(请求级)实例
|
|
|
|
|
|
*/
|
|
|
|
|
|
function container(): ContainerInterface
|
|
|
|
|
|
{
|
|
|
|
|
|
return Container::getInstance();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 解析类实例(使用容器)
|
|
|
|
|
|
*
|
2022-04-05 01:06:47 +08:00
|
|
|
|
* @template T
|
2022-05-04 22:25:42 +08:00
|
|
|
|
* @param class-string<T> $abstract
|
2022-04-05 01:14:06 +08:00
|
|
|
|
* @return Closure|mixed|T
|
2022-04-05 00:24:03 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function resolve(string $abstract, array $parameters = [])
|
|
|
|
|
|
{
|
|
|
|
|
|
return Container::getInstance()->make($abstract, $parameters);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取容器实例
|
|
|
|
|
|
*
|
2022-04-05 01:06:47 +08:00
|
|
|
|
* @template T
|
2022-04-05 01:14:06 +08:00
|
|
|
|
* @param null|class-string<T> $abstract
|
|
|
|
|
|
* @return Closure|ContainerInterface|mixed|T
|
2022-04-05 00:24:03 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function app(string $abstract = null, array $parameters = [])
|
|
|
|
|
|
{
|
|
|
|
|
|
if (is_null($abstract)) {
|
|
|
|
|
|
return container();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return resolve($abstract, $parameters);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-05-09 16:39:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 根据键名比较对象和数组
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param object $object 对象
|
|
|
|
|
|
* @param array $array 数组
|
|
|
|
|
|
* @param array $keys 键名
|
|
|
|
|
|
*/
|
|
|
|
|
|
function compare_object_and_array_by_keys(object $object, array $array, array $keys): bool
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach ($keys as $key) {
|
|
|
|
|
|
if (!isset($object->{$key}, $array[$key]) || $object->{$key} !== $array[$key]) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-05-10 00:32:20 +08:00
|
|
|
|
function is_assoc_array(array $array): bool
|
|
|
|
|
|
{
|
|
|
|
|
|
return !empty($array) && array_keys($array) !== range(0, count($array) - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 20:08:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 以下为废弃的函数,将于未来移除
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @deprecated 已废弃,请使用 {@link get_all_fd_of_type()}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getAllFdByConnectType(string $type = 'default'): array
|
|
|
|
|
|
{
|
|
|
|
|
|
return get_all_fd_of_type($type);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param mixed $class_name
|
|
|
|
|
|
* @deprecated 已废弃,请使用 {@link get_class_path()}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getClassPath($class_name): ?string
|
|
|
|
|
|
{
|
|
|
|
|
|
return get_class_path($class_name);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param mixed $msg
|
|
|
|
|
|
* @param mixed $ban_comma
|
|
|
|
|
|
* @deprecated 已废弃,请使用 {@link explode_msg()},参数有变
|
|
|
|
|
|
*/
|
|
|
|
|
|
function explodeMsg($msg, $ban_comma = false): array
|
|
|
|
|
|
{
|
|
|
|
|
|
if ($ban_comma) {
|
|
|
|
|
|
return explode_msg($msg, [' ']);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return explode_msg($msg);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @deprecated 已废弃,请使用 {@link current_connection_is()}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function connectIsQQ(): bool
|
|
|
|
|
|
{
|
|
|
|
|
|
return current_connection_is('qq');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @deprecated 已废弃,请使用 {@link current_connection_is()}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function connectIsDefault(): bool
|
|
|
|
|
|
{
|
|
|
|
|
|
return current_connection_is('default');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param mixed $type
|
|
|
|
|
|
* @deprecated 已废弃,请使用 {@link current_connection_is()}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function connectIs($type): bool
|
|
|
|
|
|
{
|
|
|
|
|
|
return current_connection_is($type);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @deprecated 已废弃,请使用 {@link get_annotations()}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getAnnotations(): array
|
|
|
|
|
|
{
|
|
|
|
|
|
return get_annotations();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param mixed $pattern
|
|
|
|
|
|
* @param mixed $context
|
|
|
|
|
|
* @deprecated 已废弃,请使用 {@link match_args()}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function matchArgs($pattern, $context)
|
|
|
|
|
|
{
|
|
|
|
|
|
return match_args($pattern, $context);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param mixed $pattern
|
|
|
|
|
|
* @param mixed $context
|
|
|
|
|
|
* @deprecated 已废弃,请使用 {@link match_pattern()}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function matchPattern($pattern, $context): bool
|
|
|
|
|
|
{
|
|
|
|
|
|
return match_pattern($pattern, $context);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2022-04-02 23:37:22 +08:00
|
|
|
|
* @param string $message_type 消息类型
|
2022-03-21 20:08:09 +08:00
|
|
|
|
* @deprecated 已废弃,请使用 {@link get_onebot_target_id_name()}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function onebot_target_id_name(string $message_type): string
|
|
|
|
|
|
{
|
|
|
|
|
|
return get_onebot_target_id_name($message_type);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @deprecated 已废弃,请直接使用 {@link call_with_catch()}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function zm_go(callable $callable)
|
|
|
|
|
|
{
|
|
|
|
|
|
call_with_catch($callable);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param mixed $v
|
|
|
|
|
|
* @deprecated 已废弃,请使用 {@link hash_message()}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function zm_data_hash($v): string
|
|
|
|
|
|
{
|
|
|
|
|
|
return hash_message($v);
|
|
|
|
|
|
}
|