Files
zhamao-framework/src/ZM/global_functions.php
jerry d699a152d5 update to 2.4.2 version (build 402)
change WORKING_DIR constant
change logic of savePersistence()
add LightCache addPersistence() and removePersistence() method
add `./zhamao` command
2021-03-27 16:30:15 +08:00

379 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php #plain
use Swoole\Atomic;
use Swoole\Coroutine;
use Swoole\WebSocket\Server;
use Symfony\Component\VarDumper\VarDumper;
use ZM\API\ZMRobot;
use ZM\Config\ZMConfig;
use ZM\ConnectionManager\ManagerGM;
use ZM\Console\Console;
use ZM\Context\Context;
use ZM\Event\EventManager;
use ZM\Exception\RobotNotFoundException;
use ZM\Exception\ZMException;
use ZM\Framework;
use ZM\Store\LightCacheInside;
use ZM\Store\ZMAtomic;
use ZM\Store\ZMBuf;
use ZM\Utils\DataProvider;
use Swoole\Coroutine\System;
use ZM\Context\ContextInterface;
function getClassPath($class_name) {
$dir = str_replace("\\", "/", $class_name);
$dir2 = WORKING_DIR . "/src/" . $dir . ".php";
//echo "@@@".$dir2.PHP_EOL;
$dir2 = str_replace("\\", "/", $dir2);
if (file_exists($dir2)) return $dir2;
else return null;
}
/**
* 使用自己定义的万san能分割函数
* @param $msg
* @param bool $ban_comma
* @return array
*/
function explodeMsg($msg, $ban_comma = false): array {
$msg = str_replace(" ", "\n", trim($msg));
if (!$ban_comma) {
//$msg = str_replace("", "\n", $msg);
$msg = str_replace("\t", "\n", $msg);
}
$msgs = explode("\n", $msg);
$ls = [];
foreach ($msgs as $k => $v) {
if (trim($v) == "") continue;
$ls[] = trim($v);
}
return $ls;
}
function unicode_decode($str) {
return preg_replace_callback('/\\\\u([0-9a-f]{4})/i', function ($matches) {
return mb_convert_encoding(pack("H*", $matches[1]), "UTF-8", "UCS-2BE");
}, $str);
}
/**
* 获取模块文件夹下的每个类文件的类名称
* @param $dir
* @param $indoor_name
* @return array
*/
function getAllClasses($dir, $indoor_name): array {
if (!is_dir($dir)) return [];
$list = scandir($dir);
$classes = [];
if ($list[0] == '.') unset($list[0], $list[1]);
foreach ($list as $v) {
//echo "Finding " . $dir . $v . PHP_EOL;
//echo "At " . $indoor_name . PHP_EOL;
if (is_dir($dir . $v)) $classes = array_merge($classes, getAllClasses($dir . $v . "/", $indoor_name . "\\" . $v));
elseif (mb_substr($v, -4) == ".php") {
if (substr(file_get_contents($dir . $v), 6, 6) == "#plain") continue;
$composer = json_decode(file_get_contents(DataProvider::getWorkingDir() . "/composer.json"), true);
foreach ($composer["autoload"]["files"] as $fi) {
if (realpath(DataProvider::getWorkingDir() . "/" . $fi) == realpath($dir . $v)) {
continue 2;
}
}
if ($v == "global_function.php") continue;
$class_name = $indoor_name . "\\" . mb_substr($v, 0, -4);
$classes [] = $class_name;
}
}
return $classes;
}
function matchPattern($pattern, $context): bool {
if (mb_substr($pattern, 0, 1) == "" && mb_substr($context, 0, 1) == "")
return true;
if ('*' == mb_substr($pattern, 0, 1) && "" != mb_substr($pattern, 1, 1) && "" == mb_substr($context, 0, 1))
return false;
if (mb_substr($pattern, 0, 1) == mb_substr($context, 0, 1))
return matchPattern(mb_substr($pattern, 1), mb_substr($context, 1));
if (mb_substr($pattern, 0, 1) == "*")
return matchPattern(mb_substr($pattern, 1), $context) || matchPattern($pattern, mb_substr($context, 1));
return false;
}
function split_explode($del, $str, $divide_en = false): array {
$str = explode($del, $str);
for ($i = 0; $i < mb_strlen($str[0]); $i++) {
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
)
) {
$str[0] = mb_substr($str[0], 0, $i) . " " . mb_substr($str[0], $i);
} 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) != ' '
) {
$str[0] = mb_substr($str[0], 0, $i) . ' ' . mb_substr($str[0], $i);
}
}
$str = implode($del, $str);
//echo $str."\n";
$ls = [];
foreach (explode($del, $str) as $k => $v) {
if (trim($v) == "") continue;
$ls[] = $v;
}
//var_dump($ls);
return $ls == [] ? [""] : $ls;
}
function matchArgs($pattern, $context) {
$result = [];
if (matchPattern($pattern, $context)) {
if (mb_strpos($pattern, "*") === false) return [];
$exp = explode("*", $pattern);
$i = 0;
foreach ($exp as $k => $v) {
//echo "[MATCH$k] " . $v . PHP_EOL;
if ($v == "" && $k == 0) continue;
elseif ($v == "" && $k == count($exp) - 1) {
$context = $context . "^EOL";
$v = "^EOL";
}
$cur_var = "";
//echo mb_substr($context, $i) . "|" . $v . PHP_EOL;
$ori = $i;
while (($a = mb_substr($context, $i, mb_strlen($v))) != $v && $a != "") {
$cur_var .= mb_substr($context, $i, 1);
++$i;
}
if ($i != $ori || $k == 1 || $k == count($exp) - 1) {
//echo $cur_var . PHP_EOL;
$result[] = $cur_var;
}
$i += mb_strlen($v);
}
return $result;
} else return false;
}
function connectIsQQ(): bool {
return ctx()->getConnection()->getName() == 'qq';
}
function connectIsDefault(): bool {
return ctx()->getConnection()->getName() == 'default';
}
function connectIs($type): bool {
return ctx()->getConnection()->getName() == $type;
}
function getAnnotations(): array {
$s = debug_backtrace()[1];
//echo json_encode($s, 128|256);
$list = [];
foreach (EventManager::$events as $event => $v) {
foreach ($v as $ks => $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;
}
}
}
return $list;
}
function set_coroutine_params($array) {
$cid = Co::getCid();
if ($cid == -1) die("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;
foreach (Context::$context as $c => $v) {
if (!Co::exists($c)) unset(Context::$context[$c], ZMBuf::$context_class[$c]);
}
}
/**
* @return ContextInterface|null
*/
function context(): ?ContextInterface {
return ctx();
}
/**
* @return ContextInterface|null
*/
function ctx(): ?ContextInterface {
$cid = Co::getCid();
$c_class = ZMConfig::get("global", "context_class");
if (isset(Context::$context[$cid])) {
return ZMBuf::$context_class[$cid] ?? (ZMBuf::$context_class[$cid] = new $c_class($cid));
} else {
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));
}
return null;
}
}
function onebot_target_id_name($message_type): string {
return ($message_type == "group" ? "group_id" : "user_id");
}
function zm_sleep($s = 1): bool {
if (Coroutine::getCid() != -1) System::sleep($s);
else usleep($s * 1000 * 1000);
return true;
}
function zm_exec($cmd): array {
return System::exec($cmd);
}
function zm_cid() {
return Co::getCid();
}
function zm_yield() {
Co::yield();
}
function zm_resume(int $cid) {
Co::resume($cid);
}
function zm_timer_after($ms, callable $callable) {
Swoole\Timer::after($ms, function () use ($callable) {
call_with_catch($callable);
});
}
function call_with_catch($callable) {
try {
$callable();
} catch (Exception $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
Console::error("Uncaught exception " . get_class($e) . " when calling \"message\": " . $error_msg);
Console::trace();
} catch (Error $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
Console::error("Uncaught " . get_class($e) . " when calling \"message\": " . $error_msg);
Console::trace();
}
}
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);
});
}
}
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"]));
}
function server(): ?Server {
return Framework::$server;
}
/**
* @return ZMRobot
* @throws RobotNotFoundException
* @throws ZMException
*/
function bot(): ZMRobot {
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("没有任何机器人连接到框架!");
}
}
/**
* 获取同类型所有连接的文件描述符 ID
* @param string $type
* @return array
* @author 854854321
*/
function getAllFdByConnectType(string $type = 'default'): array {
$fds = [];
foreach (ManagerGM::getAllByName($type) as $obj) {
$fds[] = $obj->getFd();
}
return $fds;
}
function zm_atomic($name): ?Atomic {
return ZMAtomic::get($name);
}
function uuidgen($uppercase = false): string {
try {
$data = random_bytes(16);
} catch (Exception $e) {
return "";
}
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
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));
}
function working_dir() {
return WORKING_DIR;
}
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;
}
function zm_info($obj) { Console::info($obj); }
function zm_warning($obj) { Console::warning($obj); }
function zm_success($obj) { Console::success($obj); }
function zm_debug($obj) { Console::debug($obj); }
function zm_verbose($obj) { Console::verbose($obj); }
function zm_error($obj) { Console::error($obj); }
function zm_config($name, $key = null) { return ZMConfig::get($name, $key); }
function quick_reply_closure($reply) {
return function() use ($reply){
return $reply;
};
}