2020-09-29 15:07:43 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace ZM\Module;
|
|
|
|
|
|
|
2021-01-29 23:34:34 +08:00
|
|
|
|
use Exception;
|
2020-11-03 21:02:24 +08:00
|
|
|
|
use ZM\Annotation\CQ\CQAPIResponse;
|
|
|
|
|
|
use ZM\Annotation\CQ\CQBefore;
|
|
|
|
|
|
use ZM\Annotation\CQ\CQCommand;
|
|
|
|
|
|
use ZM\Annotation\CQ\CQMessage;
|
|
|
|
|
|
use ZM\Annotation\CQ\CQMetaEvent;
|
|
|
|
|
|
use ZM\Annotation\CQ\CQNotice;
|
|
|
|
|
|
use ZM\Annotation\CQ\CQRequest;
|
|
|
|
|
|
use ZM\Event\EventDispatcher;
|
|
|
|
|
|
use ZM\Exception\InterruptException;
|
|
|
|
|
|
use ZM\Exception\WaitTimeoutException;
|
|
|
|
|
|
use ZM\Utils\CoMessage;
|
|
|
|
|
|
|
2020-09-29 15:07:43 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* Class QQBot
|
2020-10-03 23:00:18 +08:00
|
|
|
|
* @package ZM\Module
|
2020-09-29 15:07:43 +08:00
|
|
|
|
*/
|
|
|
|
|
|
class QQBot
|
|
|
|
|
|
{
|
2020-11-03 21:02:24 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @throws InterruptException
|
2021-01-29 23:34:34 +08:00
|
|
|
|
* @throws Exception
|
2020-11-03 21:02:24 +08:00
|
|
|
|
*/
|
2020-09-29 15:07:43 +08:00
|
|
|
|
public function handle() {
|
2020-11-03 21:02:24 +08:00
|
|
|
|
try {
|
|
|
|
|
|
$data = json_decode(context()->getFrame()->data, true);
|
2021-01-29 23:34:34 +08:00
|
|
|
|
set_coroutine_params(["data" => $data]);
|
2020-11-03 21:02:24 +08:00
|
|
|
|
if (isset($data["post_type"])) {
|
|
|
|
|
|
//echo TermColor::ITALIC.json_encode($data, 128|256).TermColor::RESET.PHP_EOL;
|
|
|
|
|
|
ctx()->setCache("level", 0);
|
|
|
|
|
|
//Console::debug("Calling CQ Event from fd=" . ctx()->getConnection()->getFd());
|
2021-01-02 13:15:50 +08:00
|
|
|
|
if ($data["post_type"] != "meta_event") {
|
|
|
|
|
|
$r = $this->dispatchBeforeEvents($data); // before在这里执行,元事件不执行before为减少不必要的调试日志
|
|
|
|
|
|
if ($r->store === "block") EventDispatcher::interrupt();
|
|
|
|
|
|
}
|
2020-11-03 21:02:24 +08:00
|
|
|
|
//Console::warning("最上数据包:".json_encode($data));
|
|
|
|
|
|
}
|
2021-01-30 00:06:42 +08:00
|
|
|
|
if (isset($data["echo"]) || isset($data["post_type"])) {
|
|
|
|
|
|
if (CoMessage::resumeByWS()) EventDispatcher::interrupt();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (isset($data["post_type"])) $this->dispatchEvents($data);
|
|
|
|
|
|
else $this->dispatchAPIResponse($data);
|
2020-11-03 21:02:24 +08:00
|
|
|
|
} /** @noinspection PhpRedundantCatchClauseInspection */ catch (WaitTimeoutException $e) {
|
|
|
|
|
|
$e->module->finalReply($e->getMessage());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-01-02 13:15:50 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @param $data
|
|
|
|
|
|
* @return EventDispatcher
|
2021-01-29 23:34:34 +08:00
|
|
|
|
* @throws Exception
|
2021-01-02 13:15:50 +08:00
|
|
|
|
*/
|
2020-11-03 21:02:24 +08:00
|
|
|
|
public function dispatchBeforeEvents($data) {
|
|
|
|
|
|
$before = new EventDispatcher(CQBefore::class);
|
|
|
|
|
|
$before->setRuleFunction(function ($v) use ($data) {
|
2020-12-31 16:26:51 +08:00
|
|
|
|
return $v->cq_event == $data["post_type"];
|
2020-11-03 21:02:24 +08:00
|
|
|
|
});
|
|
|
|
|
|
$before->setReturnFunction(function ($result) {
|
2021-01-02 13:15:50 +08:00
|
|
|
|
if (!$result) EventDispatcher::interrupt("block");
|
2020-11-03 21:02:24 +08:00
|
|
|
|
});
|
|
|
|
|
|
$before->dispatchEvents($data);
|
2021-01-02 13:15:50 +08:00
|
|
|
|
return $before;
|
2020-11-03 21:02:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-01-02 13:15:50 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @param $data
|
|
|
|
|
|
* @throws InterruptException
|
|
|
|
|
|
*/
|
2020-11-03 21:02:24 +08:00
|
|
|
|
private function dispatchEvents($data) {
|
|
|
|
|
|
//Console::warning("最xia数据包:".json_encode($data));
|
|
|
|
|
|
switch ($data["post_type"]) {
|
|
|
|
|
|
case "message":
|
2020-11-04 18:43:50 +08:00
|
|
|
|
$word = explodeMsg(str_replace("\r", "", context()->getMessage()));
|
2021-01-18 18:08:29 +08:00
|
|
|
|
if (empty($word)) $word = [""];
|
2020-11-03 21:02:24 +08:00
|
|
|
|
if (count(explode("\n", $word[0])) >= 2) {
|
|
|
|
|
|
$enter = explode("\n", context()->getMessage());
|
|
|
|
|
|
$first = split_explode(" ", array_shift($enter));
|
|
|
|
|
|
$word = array_merge($first, $enter);
|
|
|
|
|
|
foreach ($word as $k => $v) {
|
|
|
|
|
|
$word[$k] = trim($word[$k]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//分发CQCommand事件
|
|
|
|
|
|
$dispatcher = new EventDispatcher(CQCommand::class);
|
2020-11-04 18:43:50 +08:00
|
|
|
|
$dispatcher->setRuleFunction(function (CQCommand $v) use ($word) {
|
2021-01-02 13:15:50 +08:00
|
|
|
|
if (array_diff([$v->match, $v->pattern, $v->regex, $v->keyword, $v->end_with, $v->start_with], [""]) == []) return false;
|
2020-11-03 21:02:24 +08:00
|
|
|
|
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->message_type == '' || ($v->message_type != '' && $v->message_type == ctx()->getMessageType()))
|
|
|
|
|
|
) {
|
2021-01-02 13:15:50 +08:00
|
|
|
|
if (($word[0] != "" && $v->match == $word[0]) || in_array($word[0], $v->alias)) {
|
2020-12-14 01:24:34 +08:00
|
|
|
|
array_shift($word);
|
2020-11-04 18:43:50 +08:00
|
|
|
|
ctx()->setCache("match", $word);
|
2020-11-03 21:02:24 +08:00
|
|
|
|
return true;
|
2020-12-10 16:37:04 +08:00
|
|
|
|
} elseif ($v->start_with != "" && mb_strpos(ctx()->getMessage(), $v->start_with) === 0) {
|
|
|
|
|
|
ctx()->setCache("match", [mb_substr(ctx()->getMessage(), mb_strlen($v->start_with))]);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} 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))]);
|
|
|
|
|
|
return true;
|
2020-12-14 01:24:34 +08:00
|
|
|
|
} elseif ($v->keyword != "" && mb_strpos(ctx()->getMessage(), $v->keyword) !== false) {
|
|
|
|
|
|
ctx()->setCache("match", explode($v->keyword, ctx()->getMessage()));
|
|
|
|
|
|
return true;
|
2021-01-02 13:15:50 +08:00
|
|
|
|
} elseif ($v->pattern != "") {
|
2020-11-04 18:43:50 +08:00
|
|
|
|
$match = matchArgs($v->pattern, ctx()->getMessage());
|
2021-01-02 13:15:50 +08:00
|
|
|
|
if ($match !== false) {
|
2020-11-04 18:43:50 +08:00
|
|
|
|
ctx()->setCache("match", $match);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
} elseif ($v->regex != "") {
|
2021-01-02 13:15:50 +08:00
|
|
|
|
if (preg_match("/" . $v->regex . "/u", ctx()->getMessage(), $word2) != 0) {
|
2020-11-04 18:43:50 +08:00
|
|
|
|
ctx()->setCache("match", $word2);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2020-11-03 21:02:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
});
|
|
|
|
|
|
$dispatcher->setReturnFunction(function ($result) {
|
|
|
|
|
|
if (is_string($result)) ctx()->reply($result);
|
2021-01-02 13:15:50 +08:00
|
|
|
|
if (ctx()->getCache("has_reply") === true) EventDispatcher::interrupt();
|
2020-11-03 21:02:24 +08:00
|
|
|
|
});
|
2021-01-02 13:15:50 +08:00
|
|
|
|
$dispatcher->dispatchEvents();
|
|
|
|
|
|
if ($dispatcher->status == EventDispatcher::STATUS_INTERRUPTED) EventDispatcher::interrupt();
|
2020-11-03 21:02:24 +08:00
|
|
|
|
|
|
|
|
|
|
//分发CQMessage事件
|
|
|
|
|
|
$msg_dispatcher = new EventDispatcher(CQMessage::class);
|
|
|
|
|
|
$msg_dispatcher->setRuleFunction(function ($v) {
|
|
|
|
|
|
return ($v->message == '' || ($v->message != '' && $v->message == context()->getData()["message"])) &&
|
|
|
|
|
|
($v->user_id == 0 || ($v->user_id != 0 && $v->user_id == context()->getData()["user_id"])) &&
|
|
|
|
|
|
($v->group_id == 0 || ($v->group_id != 0 && $v->group_id == (context()->getData()["group_id"] ?? 0))) &&
|
|
|
|
|
|
($v->message_type == '' || ($v->message_type != '' && $v->message_type == context()->getData()["message_type"])) &&
|
|
|
|
|
|
($v->raw_message == '' || ($v->raw_message != '' && $v->raw_message == context()->getData()["raw_message"]));
|
|
|
|
|
|
});
|
|
|
|
|
|
$msg_dispatcher->setReturnFunction(function ($result) {
|
|
|
|
|
|
if (is_string($result)) ctx()->reply($result);
|
|
|
|
|
|
});
|
|
|
|
|
|
$msg_dispatcher->dispatchEvents(ctx()->getMessage());
|
|
|
|
|
|
return;
|
|
|
|
|
|
case "meta_event":
|
|
|
|
|
|
//Console::success("当前数据包:".json_encode(ctx()->getData()));
|
|
|
|
|
|
$dispatcher = new EventDispatcher(CQMetaEvent::class);
|
|
|
|
|
|
$dispatcher->setRuleFunction(function (CQMetaEvent $v) {
|
2020-12-31 16:26:51 +08:00
|
|
|
|
return ($v->meta_event_type == '' || ($v->meta_event_type != '' && $v->meta_event_type == ctx()->getData()["meta_event_type"]));
|
2020-11-03 21:02:24 +08:00
|
|
|
|
});
|
|
|
|
|
|
//eval(BP);
|
|
|
|
|
|
$dispatcher->dispatchEvents(ctx()->getData());
|
|
|
|
|
|
return;
|
|
|
|
|
|
case "notice":
|
|
|
|
|
|
$dispatcher = new EventDispatcher(CQNotice::class);
|
|
|
|
|
|
$dispatcher->setRuleFunction(function (CQNotice $v) {
|
|
|
|
|
|
return
|
|
|
|
|
|
($v->notice_type == '' || ($v->notice_type != '' && $v->notice_type == ctx()->getData()["notice_type"])) &&
|
|
|
|
|
|
($v->sub_type == '' || ($v->sub_type != '' && $v->sub_type == ctx()->getData()["sub_type"])) &&
|
|
|
|
|
|
($v->group_id == '' || ($v->group_id != '' && $v->group_id == ctx()->getData()["group_id"])) &&
|
|
|
|
|
|
($v->operator_id == '' || ($v->operator_id != '' && $v->operator_id == ctx()->getData()["operator_id"]));
|
|
|
|
|
|
});
|
|
|
|
|
|
$dispatcher->dispatchEvents(ctx()->getData());
|
|
|
|
|
|
return;
|
|
|
|
|
|
case "request":
|
|
|
|
|
|
$dispatcher = new EventDispatcher(CQRequest::class);
|
|
|
|
|
|
$dispatcher->setRuleFunction(function (CQRequest $v) {
|
|
|
|
|
|
return ($v->request_type == '' || ($v->request_type != '' && $v->request_type == ctx()->getData()['request_type'])) &&
|
|
|
|
|
|
($v->sub_type == '' || ($v->sub_type != '' && $v->sub_type == ctx()->getData()['sub_type'])) &&
|
|
|
|
|
|
($v->user_id == 0 || ($v->user_id != 0 && $v->user_id == ctx()->getData()["user_id"])) &&
|
|
|
|
|
|
($v->comment == '' || ($v->comment != '' && $v->comment == ctx()->getData()['comment']));
|
|
|
|
|
|
});
|
|
|
|
|
|
$dispatcher->dispatchEvents(ctx()->getData());
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-01-29 23:34:34 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @param $req
|
|
|
|
|
|
* @throws Exception
|
|
|
|
|
|
*/
|
2020-11-03 21:02:24 +08:00
|
|
|
|
private function dispatchAPIResponse($req) {
|
2021-01-29 23:34:34 +08:00
|
|
|
|
set_coroutine_params(["cq_response" => $req]);
|
|
|
|
|
|
$dispatcher = new EventDispatcher(CQAPIResponse::class);
|
|
|
|
|
|
$dispatcher->setRuleFunction(function (CQAPIResponse $response) {
|
|
|
|
|
|
return $response->retcode == ctx()->getCQResponse()["retcode"];
|
|
|
|
|
|
});
|
|
|
|
|
|
$dispatcher->dispatchEvents($req);
|
2020-09-29 15:07:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|