diff --git a/.gitignore b/.gitignore index 5ff2aa0..5ef1fa4 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ composer.lock # phpunit .phpunit.cache .phpunit.result.cache +.idea diff --git a/src/Dialog.php b/src/Dialog.php index e2d1196..ad176d7 100644 --- a/src/Dialog.php +++ b/src/Dialog.php @@ -1,4 +1,5 @@ - Key-value storage to store data between steps. */ protected array $memory = []; @@ -29,9 +32,13 @@ abstract class Dialog /** @var int|null Index of the next step that set manually using jump() method. */ private ?int $afterProceedJumpToIndex = null; - public function __construct(int $chatId, Api $bot = null) + public function __construct(Update $update, Api $bot = null) { - $this->chat_id = $chatId; + $message = $update->getMessage(); + + $this->chatId = $message->chat->id; + $this->userId = $message->from->id; + if ($bot) { $this->bot = $bot; } @@ -59,11 +66,11 @@ final public function start(Update $update): void */ final public function proceed(Update $update): void { - $currentStepIndex = $this->next; + $currentStepIndex = $this->next; - if ($this->isStart()) { - $this->beforeAllStep($update); - } + if ($this->isStart()) { + $this->beforeAllStep($update); + } if ($this->isEnd()) { $this->afterAllStep($update); @@ -159,14 +166,12 @@ final protected function forget(string $key): void unset($this->memory[$key]); } - /** Check if Dialog started */ final public function isStart(): bool { return $this->next === 0; } - /** Check if Dialog ended */ final public function isEnd(): bool { @@ -174,9 +179,14 @@ final public function isEnd(): bool } /** Returns Telegram Chat ID */ - final public function getChatId(): int + final public function getChatId(): ?int { - return $this->chat_id; + return $this->chatId; + } + + final public function getUserId(): ?int + { + return $this->userId; } /** Get a number of seconds to store state of the Dialog after latest activity on it. */ @@ -191,7 +201,7 @@ final public function ttl(): int */ private function proceedConfiguredStep(array $stepConfig, Update $update, int $currentStepIndex): void { - if (!isset($stepConfig['name'])) { + if (! isset($stepConfig['name'])) { throw new InvalidDialogStep('Configurable Dialog step does not contain required “name” value.'); } @@ -200,17 +210,17 @@ private function proceedConfiguredStep(array $stepConfig, Update $update, int $c if (isset($stepConfig['response'])) { $params = [ 'chat_id' => $this->getChatId(), - 'text' => $stepConfig['response'], + 'text' => $stepConfig['response'], ]; - if (!empty($stepConfig['options'])) { + if (! empty($stepConfig['options'])) { $params = array_merge($params, $stepConfig['options']); } $this->bot->sendMessage($params); } - if (!empty($stepConfig['jump'])) { + if (! empty($stepConfig['jump'])) { $this->jump($stepConfig['jump']); } @@ -225,9 +235,15 @@ private function proceedConfiguredStep(array $stepConfig, Update $update, int $c public function __serialize(): array { return [ - 'chat_id' => $this->getChatId(), - 'next' => $this->next, + 'chatId' => $this->getChatId(), + 'userId' => $this->getUserId(), + 'next' => $this->next, 'memory' => $this->memory, ]; } + + public function getDialogKey(): string + { + return implode('-', [$this->getUserId(), $this->getChatId()]); + } } diff --git a/src/DialogManager.php b/src/DialogManager.php index 77901d0..c45b94f 100644 --- a/src/DialogManager.php +++ b/src/DialogManager.php @@ -6,6 +6,7 @@ use Telegram\Bot\Api; use Telegram\Bot\Objects\Message; use Telegram\Bot\Objects\Update; +use Illuminate\Support\Collection; final class DialogManager { @@ -42,11 +43,9 @@ private function getDialogInstance(Update $update): ?Dialog return null; } - $message = $update->getMessage(); - assert($message instanceof \Telegram\Bot\Objects\Message); - $chatId = $message->chat->id; + $key = $this->generateDialogKey($update); - $dialog = $this->readDialogState($chatId); + $dialog = $this->readDialogState($key); $dialog->setBot($this->bot); return $dialog; @@ -67,8 +66,7 @@ public function proceed(Update $update): void $dialog->proceed($update); if ($dialog->isEnd()) { - $this->store->delete($dialog->getChatId()); - $dialog->proceed($update); + $this->store->delete($dialog->getDialogKey()); } else { $this->storeDialogState($dialog); } @@ -77,20 +75,25 @@ public function proceed(Update $update): void /** Whether Dialog exist for a given Update. */ public function exists(Update $update): bool { - $message = $update->getMessage(); - $chatId = $message instanceof Message ? $message->chat->id : null; - return $chatId && $this->store->has($chatId); + $key = $this->generateDialogKey($update); + + return $key && $this->store->has($key); } /** Store all Dialog. */ private function storeDialogState(Dialog $dialog): void { - $this->store->set($dialog->getChatId(), $dialog, $dialog->ttl()); + $this->store->set($dialog->getDialogKey(), $dialog, $dialog->ttl()); } /** Restore Dialog. */ - private function readDialogState(int $chatId): Dialog + private function readDialogState($key): Dialog + { + return $this->store->get($key); + } + + private function generateDialogKey(Update $update): string { - return $this->store->get($chatId); + return implode('-', [$update->getMessage()->from->id, $update->getChat()->id]); } }