|
@@ -0,0 +1,290 @@
|
|
|
+<?php
|
|
|
+namespace BotKit\Drivers;
|
|
|
+
|
|
|
+// Драйвер для тестов
|
|
|
+
|
|
|
+use BotKit\Events\Event;
|
|
|
+use BotKit\Events\PlainMessageEvent;
|
|
|
+use BotKit\Events\UnknownEvent;
|
|
|
+use BotKit\Events\MemberJoinedEvent;
|
|
|
+use BotKit\Events\MemberLeftEvent;
|
|
|
+use BotKit\Common\User;
|
|
|
+use BotKit\Common\Chat;
|
|
|
+use BotKit\Common\Message;
|
|
|
+use BotKit\Common\Database;
|
|
|
+use BotKit\EventAttachments\DocumentAttachment;
|
|
|
+use BotKit\EventAttachments\ImageAttachment;
|
|
|
+use BotKit\Enums\Platform;
|
|
|
+use BotKit\Enums\State;
|
|
|
+use BotKit\Enums\KeyboardButtonColor;
|
|
|
+use BotKit\Models\UserModel;
|
|
|
+use BotKit\KeyboardButtons\CallbackButton;
|
|
|
+
|
|
|
+class TestDriver implements Driver {
|
|
|
+ // Платформа бота
|
|
|
+ private Platform $platform;
|
|
|
+
|
|
|
+ // Буфер действий
|
|
|
+ private array $actions;
|
|
|
+
|
|
|
+ public function __construct() {
|
|
|
+ $this->platform = Platform::Test;
|
|
|
+ }
|
|
|
+
|
|
|
+ #region Driver
|
|
|
+
|
|
|
+ public function forThis() : bool {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function onSelected() : void {
|
|
|
+ set_error_handler([$this, "errorHandler"], E_ALL);
|
|
|
+ set_exception_handler([$this, "exceptionHandler"]);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function onProcessStart() : void {
|
|
|
+ }
|
|
|
+
|
|
|
+ public function onProcessEnd() : void {
|
|
|
+ $this->echoActions();
|
|
|
+ }
|
|
|
+
|
|
|
+ public function getEvent() : Event {
|
|
|
+ $data = json_decode(file_get_contents("php://input"));
|
|
|
+ $db = Database::getConnection();
|
|
|
+
|
|
|
+ $details = $data->details;
|
|
|
+ $chat = new Chat(42);
|
|
|
+
|
|
|
+ if ($data->type == 'callback') {
|
|
|
+ // Обратный вызов
|
|
|
+
|
|
|
+ $user = $this->getUser();
|
|
|
+ } else if ($data->type == 'botKitMsg') {
|
|
|
+ // Обычное текстовое сообщение
|
|
|
+
|
|
|
+ // Получение объекта из БД
|
|
|
+ $obj = UserModel::where([
|
|
|
+ ['platform_id', '=', $details->userID],
|
|
|
+ ['platform', '=', $this->platform->value]
|
|
|
+ ]);
|
|
|
+
|
|
|
+ if ($obj === false) {
|
|
|
+ // Пользователя нет в БД
|
|
|
+ $obj = UserModel::create(
|
|
|
+ $details->userID,
|
|
|
+ $this->platform->value,
|
|
|
+ State::HelloWorld->value
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ $state_obj = State::from($obj['state']);
|
|
|
+
|
|
|
+ $user = new User(
|
|
|
+ $details->userID,
|
|
|
+ $state_obj,
|
|
|
+ "Test username",
|
|
|
+ $obj
|
|
|
+ );
|
|
|
+ $text = $details->text;
|
|
|
+
|
|
|
+ return new PlainMessageEvent(
|
|
|
+ $details->id,
|
|
|
+ $user,
|
|
|
+ $chat,
|
|
|
+ $text,
|
|
|
+ []
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ return new UnknownEvent();
|
|
|
+ }
|
|
|
+
|
|
|
+ public function reply(PlainMessageEvent $e, Message $msg, bool $empathise = true) {
|
|
|
+ if ($empathise) {
|
|
|
+ $reply_to_id = $e->getMessageID();
|
|
|
+ } else {
|
|
|
+ $reply_to_id = -1;
|
|
|
+ }
|
|
|
+ $this->sendInternal($msg, $reply_to_id);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function sendMessage(User $u, Message $msg) {
|
|
|
+ $this->sendInternal($msg, -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function sendToChat(Chat $chat, Message $msg) {
|
|
|
+ $this->sendInternal($msg, -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function getUserNick(User $u) : string {
|
|
|
+ return $u->getNick();
|
|
|
+ }
|
|
|
+
|
|
|
+ public function onUserSave(User $user) : void {
|
|
|
+ $this->actions[] = [
|
|
|
+ "action" => "info",
|
|
|
+ "title" => "Состояние пользователя изменено",
|
|
|
+ "body" => "Новое состояние: ".serialize($user->getState())
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ // Выводит все события в JSON
|
|
|
+ private function echoActions() {
|
|
|
+ echo json_encode($this->actions);
|
|
|
+ exit();
|
|
|
+ }
|
|
|
+
|
|
|
+ public function errorHandler(
|
|
|
+ int $errno,
|
|
|
+ string $errstr,
|
|
|
+ string $errfile = null,
|
|
|
+ int $errline = null,
|
|
|
+ array $errcontext = null
|
|
|
+ ): bool {
|
|
|
+
|
|
|
+ $meaning = [
|
|
|
+ E_ERROR => "error",
|
|
|
+ E_WARNING => "warning",
|
|
|
+ E_PARSE => "error",
|
|
|
+ E_NOTICE => "warning",
|
|
|
+ E_CORE_ERROR => "error",
|
|
|
+ E_CORE_WARNING => "warning",
|
|
|
+ E_COMPILE_ERROR => "error",
|
|
|
+ E_COMPILE_WARNING => "warning",
|
|
|
+ E_USER_ERROR => "error",
|
|
|
+ E_USER_WARNING => "warning",
|
|
|
+ E_USER_NOTICE => "warning",
|
|
|
+ E_STRICT => "warning",
|
|
|
+ E_RECOVERABLE_ERROR => "error",
|
|
|
+ E_DEPRECATED => "warning",
|
|
|
+ E_USER_DEPRECATED => "warning"
|
|
|
+ ];
|
|
|
+
|
|
|
+ $this->actions[] = [
|
|
|
+ "action" => $meaning[$errno]."Message",
|
|
|
+ "error" => [
|
|
|
+ "line" => $errline,
|
|
|
+ "file" => $errfile,
|
|
|
+ "trace" => "<Нет стека вызовов>",
|
|
|
+ "msg" => $errstr
|
|
|
+ ]
|
|
|
+ ];
|
|
|
+
|
|
|
+ if ($meaning[$errno] === 'error') {
|
|
|
+ // Если произошла фатальная ошибка, завершаем работу
|
|
|
+ $this->echoActions();
|
|
|
+ return true; // Не достигается
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public function exceptionHandler($ex) : void {
|
|
|
+ $this->actions[] = [
|
|
|
+ "action" => "errorMessage",
|
|
|
+ "error" => [
|
|
|
+ "line" => $ex->getLine(),
|
|
|
+ "file" => $ex->getFile(),
|
|
|
+ "trace" => $ex->getTraceAsString(),
|
|
|
+ "msg" => $ex->getMessage()
|
|
|
+ ]
|
|
|
+ ];
|
|
|
+ $this->echoActions();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Отправляет сообщение
|
|
|
+ private function sendInternal(Message $msg, int $reply_to_id) : void {
|
|
|
+ $attachments = [];
|
|
|
+
|
|
|
+ // Поиск клавиатур
|
|
|
+ if ($msg->hasKeyboard()) {
|
|
|
+ $keyboard = $msg->getKeyboard();
|
|
|
+
|
|
|
+ // Определение типа
|
|
|
+ if ($keyboard->inline) {
|
|
|
+ $attachment_type = "inlineKeyboard";
|
|
|
+ } else {
|
|
|
+ $attachment_type = "keyboard";
|
|
|
+ }
|
|
|
+
|
|
|
+ $serialized_layout = [];
|
|
|
+
|
|
|
+ // Разметка
|
|
|
+ $layout = $keyboard->getLayout();
|
|
|
+ foreach ($layout as $row) {
|
|
|
+ $serialized_row = [];
|
|
|
+ foreach ($row as $button) {
|
|
|
+
|
|
|
+ // Определение типа
|
|
|
+ if (is_a($button, CallbackButton::class)) {
|
|
|
+ // Кнопка обратного вызова
|
|
|
+ $button_type = "callbackButton";
|
|
|
+ } else {
|
|
|
+ $button_type = "button";
|
|
|
+ }
|
|
|
+
|
|
|
+ // Определение цвета
|
|
|
+ switch ($button->getColor()) {
|
|
|
+ case KeyboardButtonColor::Primary:
|
|
|
+ $button_color = "primary";
|
|
|
+ break;
|
|
|
+ case KeyboardButtonColor::Secondary:
|
|
|
+ $button_color = "secondary";
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ $button_color = "primary";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ $serialized_row[] = [
|
|
|
+ "type" => $button_type,
|
|
|
+ "color" => $button_color,
|
|
|
+ "label" => $button->getText(),
|
|
|
+ "payload" => $button->getPayload()
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ $serialized_layout[] = $serialized_row;
|
|
|
+ }
|
|
|
+
|
|
|
+ $attachments[] = [
|
|
|
+ "type" => $attachment_type,
|
|
|
+ "layout" => $serialized_layout
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // Поиск изображений
|
|
|
+ if ($msg->hasImages()) {
|
|
|
+ $images = $msg->getImages();
|
|
|
+ foreach ($images as $image) {
|
|
|
+ $attachments[] = [
|
|
|
+ 'type' => 'image',
|
|
|
+ 'url' => $image->getValue()
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->actions[] = [
|
|
|
+ "action" => "newMessage",
|
|
|
+ "message" => [
|
|
|
+ "text" => $msg->getText(),
|
|
|
+ "reply_to" => $reply_to_id,
|
|
|
+ "attachments" => $attachments
|
|
|
+ ]
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // Информация о переменной
|
|
|
+ public function varDump(string $title, $variable) {
|
|
|
+ ob_start();
|
|
|
+ var_dump($variable);
|
|
|
+ $info = ob_get_clean();
|
|
|
+ $this->actions[] = [
|
|
|
+ "action" => "varDump",
|
|
|
+ "title" => $title,
|
|
|
+ "info" => $info
|
|
|
+ ];
|
|
|
+ }
|
|
|
+}
|