Files
zhamao-framework/src/ZM/global_functions.php

472 lines
12 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
use Swoole\Atomic;
2020-11-03 21:02:24 +08:00
use Swoole\Coroutine;
use Swoole\Coroutine as Co;
use Swoole\Coroutine\System;
use Swoole\WebSocket\Server;
use Symfony\Component\VarDumper\VarDumper;
2021-06-16 00:17:30 +08:00
use ZM\API\OneBotV11;
2020-08-31 10:11:06 +08:00
use ZM\Config\ZMConfig;
use ZM\ConnectionManager\ManagerGM;
2020-08-31 10:11:06 +08:00
use ZM\Console\Console;
2020-09-29 15:07:43 +08:00
use ZM\Context\Context;
use ZM\Context\ContextInterface;
2020-09-29 15:07:43 +08:00
use ZM\Event\EventManager;
use ZM\Exception\RobotNotFoundException;
use ZM\Exception\ZMException;
use ZM\Exception\ZMKnownException;
2020-08-31 10:11:06 +08:00
use ZM\Framework;
use ZM\Store\LightCacheInside;
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-13 22:47:11 +08:00
function getClassPath($class_name)
{
$dir = str_replace('\\', '/', $class_name);
$dir2 = DataProvider::getSourceRootDir() . '/src/' . $dir . '.php';
// echo "@@@".$dir2.PHP_EOL;
$dir2 = str_replace('\\', '/', $dir2);
if (file_exists($dir2)) {
return $dir2;
}
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
/**
* 检查炸毛框架运行的环境
* @internal
*/
2022-03-13 22:47:11 +08:00
function _zm_env_check()
{
if (!extension_loaded('swoole')) {
exit(zm_internal_errcode('E00001') . "Can not find swoole extension.\n");
}
if (version_compare(SWOOLE_VERSION, '4.5.0') == -1) {
exit(zm_internal_errcode('E00002') . 'You must install swoole version >= 4.5.0 !');
}
if (version_compare(PHP_VERSION, '7.2') == -1) {
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
/**
* 使用自己定义的万san能分割函数
* @param $msg
* @param bool $ban_comma
*/
2022-03-13 22:47:11 +08:00
function explodeMsg($msg, $ban_comma = false): array
{
$msg = str_replace(' ', "\n", trim($msg));
2020-03-02 16:14:20 +08:00
if (!$ban_comma) {
// $msg = str_replace("", "\n", $msg);
2020-03-02 16:14:20 +08:00
$msg = str_replace("\t", "\n", $msg);
}
$msgs = explode("\n", $msg);
$ls = [];
2021-06-16 00:17:30 +08:00
foreach ($msgs as $v) {
if (trim($v) == '') {
continue;
}
2020-03-02 16:14:20 +08:00
$ls[] = trim($v);
}
return $ls;
}
2021-06-16 00:17:30 +08:00
/** @noinspection PhpUnused */
2022-03-13 22:47:11 +08:00
function unicode_decode($str)
{
2020-03-02 16:14:20 +08:00
return preg_replace_callback('/\\\\u([0-9a-f]{4})/i', function ($matches) {
return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UCS-2BE');
2020-03-02 16:14:20 +08:00
}, $str);
}
2022-03-13 22:47:11 +08:00
function matchPattern($pattern, $context): bool
{
if (mb_substr($pattern, 0, 1) == '' && mb_substr($context, 0, 1) == '') {
2020-03-02 16:14:20 +08:00
return true;
}
if (mb_substr($pattern, 0, 1) == '*' && mb_substr($pattern, 1, 1) != '' && mb_substr($context, 0, 1) == '') {
2020-03-02 16:14:20 +08:00
return false;
}
if (mb_substr($pattern, 0, 1) == mb_substr($context, 0, 1)) {
2020-03-02 16:14:20 +08:00
return matchPattern(mb_substr($pattern, 1), mb_substr($context, 1));
}
if (mb_substr($pattern, 0, 1) == '*') {
2020-03-02 16:14:20 +08:00
return matchPattern(mb_substr($pattern, 1), $context) || matchPattern($pattern, mb_substr($context, 1));
}
2020-03-02 16:14:20 +08:00
return false;
}
2022-03-13 22:47:11 +08:00
function split_explode($del, $str, $divide_en = false): array
{
2020-03-02 16:14:20 +08:00
$str = explode($del, $str);
for ($i = 0; $i < mb_strlen($str[0]); ++$i) {
2020-03-02 16:14:20 +08:00
if (
is_numeric(mb_substr($str[0], $i, 1))
&& (
!is_numeric(mb_substr($str[0], $i - 1, 1))
&& mb_substr($str[0], $i - 1, 1) != ' '
&& ctype_alpha(mb_substr($str[0], $i - 1, 1)) === false
2020-03-02 16:14:20 +08:00
)
) {
$str[0] = mb_substr($str[0], 0, $i) . ' ' . mb_substr($str[0], $i);
2020-03-02 16:14:20 +08:00
} elseif (
$divide_en
&& ctype_alnum(mb_substr($str[0], $i, 1))
&& !ctype_alnum(mb_substr($str[0], $i - 1, 1))
&& 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);
// echo $str."\n";
2020-03-02 16:14:20 +08:00
$ls = [];
2021-06-16 00:17:30 +08:00
foreach (explode($del, $str) as $v) {
if (trim($v) == '') {
continue;
}
2020-03-02 16:14:20 +08:00
$ls[] = $v;
}
// var_dump($ls);
return $ls == [] ? [''] : $ls;
2020-03-02 16:14:20 +08:00
}
2022-03-13 22:47:11 +08:00
function matchArgs($pattern, $context)
{
2020-03-02 16:14:20 +08:00
$result = [];
if (matchPattern($pattern, $context)) {
if (mb_strpos($pattern, '*') === false) {
return [];
}
$exp = explode('*', $pattern);
2020-03-02 16:14:20 +08:00
$i = 0;
foreach ($exp as $k => $v) {
// echo "[MATCH$k] " . $v . PHP_EOL;
if ($v == '' && $k == 0) {
continue;
2020-03-02 16:14:20 +08:00
}
if ($v == '' && $k == count($exp) - 1) {
$context = $context . '^EOL';
$v = '^EOL';
}
$cur_var = '';
// echo mb_substr($context, $i) . "|" . $v . PHP_EOL;
2020-03-02 16:14:20 +08:00
$ori = $i;
while (($a = mb_substr($context, $i, mb_strlen($v))) != $v && $a != '') {
2020-03-02 16:14:20 +08:00
$cur_var .= mb_substr($context, $i, 1);
++$i;
}
if ($i != $ori || $k == 1 || $k == count($exp) - 1) {
// echo $cur_var . PHP_EOL;
2020-03-02 16:14:20 +08:00
$result[] = $cur_var;
}
$i += mb_strlen($v);
}
return $result;
}
return false;
}
2022-03-13 22:47:11 +08:00
function connectIsQQ(): bool
{
2020-09-29 15:07:43 +08:00
return ctx()->getConnection()->getName() == 'qq';
}
2022-03-13 22:47:11 +08:00
function connectIsDefault(): bool
{
2020-09-29 15:07:43 +08:00
return ctx()->getConnection()->getName() == 'default';
}
2022-03-13 22:47:11 +08:00
function connectIs($type): bool
{
2020-09-29 15:07:43 +08:00
return ctx()->getConnection()->getName() == $type;
}
2022-03-13 22:47:11 +08:00
function getAnnotations(): array
{
2020-09-29 15:07:43 +08:00
$s = debug_backtrace()[1];
// echo json_encode($s, 128|256);
2020-09-29 15:07:43 +08:00
$list = [];
2021-06-16 00:17:30 +08:00
foreach (EventManager::$events as $v) {
foreach ($v as $vs) {
// echo get_class($vs).": ".$vs->class." => ".$vs->method.PHP_EOL;
if ($vs->class == $s['class'] && $vs->method == $s['function']) {
$list[get_class($vs)][] = $vs;
2020-09-29 15:07:43 +08:00
}
}
}
return $list;
}
2022-03-13 22:47:11 +08:00
function set_coroutine_params($array)
{
$cid = Co::getCid();
if ($cid == -1) {
exit(zm_internal_errcode('E00061') . 'Cannot set coroutine params at none coroutine mode.');
}
if (isset(Context::$context[$cid])) {
Context::$context[$cid] = array_merge(Context::$context[$cid], $array);
} else {
Context::$context[$cid] = $array;
}
2020-09-29 15:07:43 +08:00
foreach (Context::$context as $c => $v) {
if (!Co::exists($c)) {
unset(Context::$context[$c], ZMBuf::$context_class[$c]);
}
}
}
/**
* @throws ZMKnownException
*/
function context(): ContextInterface
2022-03-13 22:47:11 +08:00
{
2020-05-23 17:23:29 +08:00
return ctx();
}
/**
* @throws ZMKnownException
*/
function ctx(): ContextInterface
2022-03-13 22:47:11 +08:00
{
$cid = Co::getCid();
$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));
}
Console::debug("未找到当前协程的上下文({$cid}),正在找父进程的上下文");
while (($pcid = Co::getPcid($cid)) !== -1) {
$cid = $pcid;
if (isset(Context::$context[$cid])) {
return ZMBuf::$context_class[$cid] ?? (ZMBuf::$context_class[$cid] = new $c_class($cid));
}
}
throw new ZMKnownException(zm_internal_errcode('E00072') . 'Unable to find context environment');
}
2022-03-13 22:47:11 +08:00
function onebot_target_id_name($message_type): string
{
return $message_type == 'group' ? 'group_id' : 'user_id';
2020-11-03 21:02:24 +08:00
}
2022-03-13 22:47:11 +08:00
function zm_sleep($s = 1): bool
{
if (Coroutine::getCid() != -1) {
System::sleep($s);
} else {
usleep($s * 1000 * 1000);
}
2020-11-03 21:02:24 +08:00
return true;
}
2020-05-23 17:23:29 +08:00
2022-03-13 22:47:11 +08:00
function zm_exec($cmd): array
{
return System::exec($cmd);
}
2020-05-23 17:23:29 +08:00
2022-03-13 22:47:11 +08:00
function zm_cid()
{
return Co::getCid();
}
2020-05-23 17:23:29 +08:00
2022-03-13 22:47:11 +08:00
function zm_yield()
{
Co::yield();
}
2020-05-23 17:23:29 +08:00
2022-03-13 22:47:11 +08:00
function zm_resume(int $cid)
{
Co::resume($cid);
}
2020-05-23 17:23:29 +08:00
2022-03-13 22:47:11 +08:00
function zm_timer_after($ms, callable $callable)
{
Swoole\Timer::after($ms, function () use ($callable) {
call_with_catch($callable);
2020-05-23 17:23:29 +08:00
});
}
2020-05-23 17:23:29 +08:00
2022-03-13 22:47:11 +08:00
function call_with_catch($callable)
{
try {
$callable();
} catch (Exception $e) {
$error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode('E00033') . 'Uncaught exception ' . get_class($e) . ': ' . $error_msg);
Console::trace();
} catch (Error $e) {
$error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode('E00033') . 'Uncaught ' . get_class($e) . ': ' . $error_msg);
Console::trace();
}
}
2022-03-13 22:47:11 +08:00
function zm_timer_tick($ms, callable $callable)
{
if (zm_cid() === -1) {
return go(function () use ($ms, $callable) {
Console::debug('Adding extra timer tick of ' . $ms . ' ms');
Swoole\Timer::tick($ms, function () use ($callable) {
call_with_catch($callable);
});
});
} else {
return Swoole\Timer::tick($ms, function () use ($callable) {
call_with_catch($callable);
});
}
2020-05-23 17:23:29 +08:00
}
2022-03-13 22:47:11 +08:00
function zm_go(callable $callable)
{
call_with_catch($callable);
}
2022-03-13 22:47:11 +08:00
function zm_data_hash($v): string
{
return md5($v['user_id'] . '^' . $v['self_id'] . '^' . $v['message_type'] . '^' . ($v[$v['message_type'] . '_id'] ?? $v['user_id']));
2020-09-29 15:07:43 +08:00
}
2022-03-13 22:47:11 +08:00
function server(): ?Server
{
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的临时目录
*/
function _zm_pid_dir(): string
{
global $_ZM_HASH;
if (!isset($_ZM_HASH)) {
$_ZM_HASH = md5(DataProvider::getWorkingDir());
}
2022-03-13 22:47:11 +08:00
return '/tmp/.zm_' . $_ZM_HASH;
}
/**
* @throws RobotNotFoundException
* @throws ZMException
* @return OneBotV11
*/
2022-03-13 22:47:11 +08:00
function bot()
{
if (($conn = LightCacheInside::get('connect', 'conn_fd')) == -2) {
2021-06-16 00:17:30 +08:00
return OneBotV11::getRandom();
}
if ($conn != -1) {
if (($obj = ManagerGM::get($conn)) !== null) {
return new OneBotV11($obj);
}
throw new RobotNotFoundException('单机器人连接模式可能连接了多个机器人!');
}
throw new RobotNotFoundException('没有任何机器人连接到框架!');
}
2020-12-25 16:40:02 +08:00
/**
* 获取同类型所有连接的文件描述符 ID
2020-12-25 16:53:44 +08:00
* @author 854854321
2020-12-25 16:40:02 +08:00
*/
2022-03-13 22:47:11 +08:00
function getAllFdByConnectType(string $type = 'default'): array
{
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 16:40:02 +08:00
return $fds;
}
2022-03-13 22:47:11 +08:00
function zm_atomic($name): ?Atomic
{
return ZMAtomic::get($name);
2021-02-21 22:17:34 +08:00
}
2022-03-13 22:47:11 +08:00
function uuidgen($uppercase = false): string
{
2021-02-21 22:17:34 +08:00
try {
$data = random_bytes(16);
} catch (Exception $e) {
return '';
2021-02-21 22:17:34 +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));
}
2022-03-13 22:47:11 +08:00
function working_dir()
{
return WORKING_DIR;
}
2022-03-13 22:47:11 +08:00
function zm_dump($var, ...$moreVars)
{
VarDumper::dump($var);
foreach ($moreVars as $v) {
VarDumper::dump($v);
}
if (1 < func_num_args()) {
return func_get_args();
}
return $var;
}
2022-03-13 22:47:11 +08:00
function zm_info($obj)
{
2021-11-02 16:01:24 +08:00
Console::info($obj);
}
2022-03-13 22:47:11 +08:00
function zm_warning($obj)
{
2021-11-02 16:01:24 +08:00
Console::warning($obj);
}
2022-03-13 22:47:11 +08:00
function zm_success($obj)
{
2021-11-02 16:01:24 +08:00
Console::success($obj);
}
2022-03-13 22:47:11 +08:00
function zm_debug($obj)
{
2021-11-02 16:01:24 +08:00
Console::debug($obj);
}
2022-03-13 22:47:11 +08:00
function zm_verbose($obj)
{
2021-11-02 16:01:24 +08:00
Console::verbose($obj);
}
2022-03-13 22:47:11 +08:00
function zm_error($obj)
{
2021-11-02 16:01:24 +08:00
Console::error($obj);
}
2022-03-13 22:47:11 +08:00
function zm_config($name, $key = null)
{
2021-11-02 16:01:24 +08:00
return ZMConfig::get($name, $key);
}
2022-03-13 22:47:11 +08:00
function quick_reply_closure($reply)
{
2021-06-16 00:17:30 +08:00
return function () use ($reply) {
return $reply;
};
}
2021-06-16 00:17:30 +08:00
2022-03-13 22:47:11 +08:00
function zm_internal_errcode($code): string
{
return "[ErrCode:{$code}] ";
2021-06-16 00:17:30 +08:00
}