Files
zhamao-framework/src/ZM/API/CQAPI.php
2022-03-31 02:24:38 +08:00

93 lines
2.7 KiB
PHP

<?php
declare(strict_types=1);
namespace ZM\API;
use Closure;
use ZM\Console\Console;
use ZM\Store\LightCacheInside;
use ZM\Store\Lock\SpinLock;
use ZM\Store\ZMAtomic;
use ZM\Utils\CoMessage;
trait CQAPI
{
/** @var null|Closure 过滤用的 */
private static $filter;
public function __call($name, $arguments)
{
return false;
}
public static function registerFilter(callable $callable)
{
self::$filter = $callable;
}
public function getActionName($suffix, string $method)
{
$postfix = ($suffix == OneBotV11::API_ASYNC ? '_async' : ($suffix == OneBotV11::API_RATE_LIMITED ? '_rate_limited' : ''));
$func_name = strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $method));
return $func_name . $postfix;
}
private function processAPI($connection, $reply, $function = null)
{
if (is_callable(self::$filter)) {
$reply2 = call_user_func(self::$filter, $reply);
if (is_bool($reply2)) {
return $reply2;
}
$reply = $reply2;
}
if ($connection->getOption('type') === CONN_WEBSOCKET) {
return $this->processWebsocketAPI($connection, $reply, $function);
}
return $this->processHttpAPI($connection, $reply, $function);
}
private function processWebsocketAPI($connection, $reply, $function = false)
{
$api_id = ZMAtomic::get('wait_msg_id')->add();
$reply['echo'] = $api_id;
if (server()->push($connection->getFd(), json_encode($reply))) {
if ($function === true) {
$obj = [
'data' => $reply,
'time' => microtime(true),
'self_id' => $connection->getOption('connect_id'),
'echo' => $api_id,
];
return CoMessage::yieldByWS($obj, ['echo'], 30);
}
return true;
}
Console::warning(zm_internal_errcode('E00036') . 'CQAPI send failed, websocket push error.');
$response = [
'status' => 'failed',
'retcode' => -1000,
'data' => null,
'self_id' => $connection->getOption('connect_id'),
];
SpinLock::lock('wait_api');
$r = LightCacheInside::get('wait_api', 'wait_api');
unset($r[$reply['echo']]);
LightCacheInside::set('wait_api', 'wait_api', $r);
SpinLock::unlock('wait_api');
if ($function === true) {
return $response;
}
return false;
}
private function processHttpAPI($connection, $reply, $function = null): bool
{
unset($connection, $reply, $function);
// TODO: HTTP方式处理API的代码还没写
return false;
}
}