Only one conversation can be active at any one time. A conversation is directly linked to a user, chat and the command that is managing the conversation.
 /**
  * Command execute method
  *
  * @return mixed
  * @throws \Longman\TelegramBot\Exception\TelegramException
  */
 public function execute()
 {
     $message = $this->getMessage();
     $chat = $message->getChat();
     $user = $message->getFrom();
     $text = trim($message->getText(true));
     $chat_id = $chat->getId();
     $user_id = $user->getId();
     //Preparing Response
     $data = ['chat_id' => $chat_id];
     if ($chat->isGroupChat() || $chat->isSuperGroup()) {
         //reply to message id is applied by default
         //Force reply is applied by default so it can work with privacy on
         $data['reply_markup'] = Keyboard::forceReply(['selective' => true]);
     }
     //Conversation start
     $this->conversation = new Conversation($user_id, $chat_id, $this->getName());
     $notes =& $this->conversation->notes;
     !is_array($notes) && ($notes = []);
     //cache data from the tracking session if any
     $state = 0;
     if (isset($notes['state'])) {
         $state = $notes['state'];
     }
     $result = Request::emptyResponse();
     //State machine
     //Entrypoint of the machine state if given by the track
     //Every time a step is achieved the track is updated
     switch ($state) {
         case 0:
             if ($text === '') {
                 $notes['state'] = 0;
                 $this->conversation->update();
                 $data['text'] = 'Type your name:';
                 $data['reply_markup'] = Keyboard::remove(['selective' => true]);
                 $result = Request::sendMessage($data);
                 break;
             }
             $notes['name'] = $text;
             $text = '';
             // no break
         // no break
         case 1:
             if ($text === '') {
                 $notes['state'] = 1;
                 $this->conversation->update();
                 $data['text'] = 'Type your surname:';
                 $result = Request::sendMessage($data);
                 break;
             }
             $notes['surname'] = $text;
             $text = '';
             // no break
         // no break
         case 2:
             if ($text === '' || !is_numeric($text)) {
                 $notes['state'] = 2;
                 $this->conversation->update();
                 $data['text'] = 'Type your age:';
                 if ($text !== '') {
                     $data['text'] = 'Type your age, must be a number:';
                 }
                 $result = Request::sendMessage($data);
                 break;
             }
             $notes['age'] = $text;
             $text = '';
             // no break
         // no break
         case 3:
             if ($text === '' || !in_array($text, ['M', 'F'], true)) {
                 $notes['state'] = 3;
                 $this->conversation->update();
                 $data['reply_markup'] = (new Keyboard(['M', 'F']))->setResizeKeyboard(true)->setOneTimeKeyboard(true)->setSelective(true);
                 $data['text'] = 'Select your gender:';
                 if ($text !== '') {
                     $data['text'] = 'Select your gender, choose a keyboard option:';
                 }
                 $result = Request::sendMessage($data);
                 break;
             }
             $notes['gender'] = $text;
             // no break
         // no break
         case 4:
             if ($message->getLocation() === null) {
                 $notes['state'] = 4;
                 $this->conversation->update();
                 $data['reply_markup'] = (new Keyboard((new KeyboardButton('Share Location'))->setRequestLocation(true)))->setOneTimeKeyboard(true)->setResizeKeyboard(true)->setSelective(true);
                 $data['text'] = 'Share your location:';
                 $result = Request::sendMessage($data);
                 break;
             }
             $notes['longitude'] = $message->getLocation()->getLongitude();
             $notes['latitude'] = $message->getLocation()->getLatitude();
             // no break
         // no break
         case 5:
             if ($message->getPhoto() === null) {
                 $notes['state'] = 5;
                 $this->conversation->update();
                 $data['text'] = 'Insert your picture:';
                 $result = Request::sendMessage($data);
                 break;
             }
             /** @var PhotoSize $photo */
             $photo = $message->getPhoto()[0];
             $notes['photo_id'] = $photo->getFileId();
             // no break
         // no break
         case 6:
             if ($message->getContact() === null) {
                 $notes['state'] = 6;
                 $this->conversation->update();
                 $data['reply_markup'] = (new Keyboard((new KeyboardButton('Share Contact'))->setRequestContact(true)))->setOneTimeKeyboard(true)->setResizeKeyboard(true)->setSelective(true);
                 $data['text'] = 'Share your contact information:';
                 $result = Request::sendMessage($data);
                 break;
             }
             $notes['phone_number'] = $message->getContact()->getPhoneNumber();
             // no break
         // no break
         case 7:
             $this->conversation->update();
             $out_text = '/Survey result:' . PHP_EOL;
             unset($notes['state']);
             foreach ($notes as $k => $v) {
                 $out_text .= PHP_EOL . ucfirst($k) . ': ' . $v;
             }
             $data['photo'] = $notes['photo_id'];
             $data['reply_markup'] = Keyboard::remove(['selective' => true]);
             $data['caption'] = $out_text;
             $this->conversation->stop();
             $result = Request::sendPhoto($data);
             break;
     }
     return $result;
 }
 /**
  * Execute command
  *
  * @return \Longman\TelegramBot\Entities\ServerResponse
  * @throws \Longman\TelegramBot\Exception\TelegramException
  */
 public function execute()
 {
     //If a conversation is busy, execute the conversation command after handling the message
     $conversation = new Conversation($this->getMessage()->getFrom()->getId(), $this->getMessage()->getChat()->getId());
     //Fetch conversation command if it exists and execute it
     if ($conversation->exists() && ($command = $conversation->getCommand())) {
         return $this->telegram->executeCommand($command);
     }
     return Request::emptyResponse();
 }
 /**
  * {@inheritdoc}
  */
 public function execute()
 {
     $text = 'No active conversation!';
     //Cancel current conversation if any
     $conversation = new Conversation($this->getMessage()->getFrom()->getId(), $this->getMessage()->getChat()->getId());
     if ($conversation_command = $conversation->getCommand()) {
         $conversation->cancel();
         $text = 'Conversation "' . $conversation_command . '" cancelled!';
     }
     return $this->hideKeyboard($text);
 }
 /**
  * @test
  */
 public function updateConversationNotes()
 {
     $info = TestHelpers::startFakeConversation('command');
     $conversation = new Conversation($info['user_id'], $info['chat_id'], 'command');
     $conversation->notes = 'newnote';
     $conversation->update();
     $conversation2 = new Conversation($info['user_id'], $info['chat_id'], 'command');
     $this->assertSame('newnote', $conversation2->notes);
     $conversation3 = new Conversation($info['user_id'], $info['chat_id']);
     $this->assertSame('newnote', $conversation3->notes);
 }
 /**
  * {@inheritdoc}
  */
 public function execute()
 {
     $message = $this->getMessage();
     $chat = $message->getChat();
     $user = $message->getFrom();
     $text = $message->getText(true);
     $chat_id = $chat->getId();
     $user_id = $user->getId();
     //Preparing Respose
     $data = [];
     if ($chat->isGroupChat() || $chat->isSuperGroup()) {
         //reply to message id is applied by default
         //Force reply is applied by default to so can work with privacy on
         $data['reply_markup'] = new ForceReply(['selective' => true]);
     }
     $data['chat_id'] = $chat_id;
     //Conversation start
     $this->conversation = new Conversation($user_id, $chat_id, $this->getName());
     //cache data from the tracking session if any
     if (!isset($this->conversation->notes['state'])) {
         $state = '0';
     } else {
         $state = $this->conversation->notes['state'];
     }
     //state machine
     //entrypoint of the machine state if given by the track
     //Every time the step is achived the track is updated
     switch ($state) {
         case 0:
             if (empty($text)) {
                 $this->conversation->notes['state'] = 0;
                 $this->conversation->update();
                 $data['text'] = 'Type your name:';
                 $data['reply_markup'] = new ReplyKeyBoardHide(['selective' => true]);
                 $result = Request::sendMessage($data);
                 break;
             }
             $this->conversation->notes['name'] = $text;
             $text = '';
             // no break
         // no break
         case 1:
             if (empty($text)) {
                 $this->conversation->notes['state'] = 1;
                 $this->conversation->update();
                 $data['text'] = 'Type your surname:';
                 $result = Request::sendMessage($data);
                 break;
             }
             $this->conversation->notes['surname'] = $text;
             ++$state;
             $text = '';
             // no break
         // no break
         case 2:
             if (empty($text) || !is_numeric($text)) {
                 $this->conversation->notes['state'] = 2;
                 $this->conversation->update();
                 $data['text'] = 'Type your age:';
                 if (!empty($text) && !is_numeric($text)) {
                     $data['text'] = 'Type your age, must be a number';
                 }
                 $result = Request::sendMessage($data);
                 break;
             }
             $this->conversation->notes['age'] = $text;
             $text = '';
             // no break
         // no break
         case 3:
             if (empty($text) || !($text == 'M' || $text == 'F')) {
                 $this->conversation->notes['state'] = 3;
                 $this->conversation->update();
                 $keyboard = [['M', 'F']];
                 $reply_keyboard_markup = new ReplyKeyboardMarkup(['keyboard' => $keyboard, 'resize_keyboard' => true, 'one_time_keyboard' => true, 'selective' => true]);
                 $data['reply_markup'] = $reply_keyboard_markup;
                 $data['text'] = 'Select your gender:';
                 if (!empty($text) && !($text == 'M' || $text == 'F')) {
                     $data['text'] = 'Select your gender, choose a keyboard option:';
                 }
                 $result = Request::sendMessage($data);
                 break;
             }
             $this->conversation->notes['gender'] = $text;
             $text = '';
             // no break
         // no break
         case 4:
             if (is_null($message->getLocation())) {
                 $this->conversation->notes['state'] = 4;
                 $this->conversation->update();
                 $data['reply_markup'] = new ReplyKeyboardMarkup(['keyboard' => [[['text' => 'Share Location', 'request_location' => true]]], 'resize_keyboard' => true, 'one_time_keyboard' => true, 'selective' => true]);
                 $data['text'] = 'Share your location:';
                 $result = Request::sendMessage($data);
                 break;
             }
             $this->conversation->notes['longitude'] = $message->getLocation()->getLongitude();
             $this->conversation->notes['latitude'] = $message->getLocation()->getLatitude();
             // no break
         // no break
         case 5:
             if (is_null($message->getPhoto())) {
                 $this->conversation->notes['state'] = 5;
                 $this->conversation->update();
                 $data['text'] = 'Insert your picture:';
                 $data['reply_markup'] = new ReplyKeyBoardHide(['selective' => true]);
                 $result = Request::sendMessage($data);
                 break;
             }
             $this->conversation->notes['photo_id'] = $message->getPhoto()[0]->getFileId();
             // no break
         // no break
         case 6:
             if (is_null($message->getContact())) {
                 $this->conversation->notes['state'] = 6;
                 $this->conversation->update();
                 $data['text'] = 'Share your contact information:';
                 $data['reply_markup'] = new ReplyKeyboardMarkup(['keyboard' => [[['text' => 'Share Contact', 'request_contact' => true]]], 'resize_keyboard' => true, 'one_time_keyboard' => true, 'selective' => true]);
                 $result = Request::sendMessage($data);
                 break;
             }
             $this->conversation->notes['phone_number'] = $message->getContact()->getPhoneNumber();
             // no break
         // no break
         case 7:
             $this->conversation->update();
             $out_text = '/Survey result:' . "\n";
             unset($this->conversation->notes['state']);
             foreach ($this->conversation->notes as $k => $v) {
                 $out_text .= "\n" . ucfirst($k) . ': ' . $v;
             }
             $data['photo'] = $this->conversation->notes['photo_id'];
             $data['reply_markup'] = new ReplyKeyBoardHide(['selective' => true]);
             $data['caption'] = $out_text;
             $this->conversation->stop();
             $result = Request::sendPhoto($data);
             break;
     }
     return $result;
 }
 /**
  * {@inheritdoc}
  */
 public function execute()
 {
     $message = $this->getMessage();
     $chat_id = $message->getChat()->getId();
     $user_id = $message->getFrom()->getId();
     $type = $message->getType();
     // 'Cast' the command type into message this protect the machine state
     // if the commmad is recolled when the conversation is already started
     $type = $type == 'command' ? 'Message' : $type;
     $text = trim($message->getText(true));
     $data = [];
     $data['chat_id'] = $chat_id;
     // Conversation
     $this->conversation = new Conversation($user_id, $chat_id, $this->getName());
     $channels = (array) $this->getConfig('your_channel');
     if (!isset($this->conversation->notes['state'])) {
         $state = count($channels) == 0 ? -1 : 0;
         $this->conversation->notes['last_message_id'] = $message->getMessageId();
     } else {
         $state = $this->conversation->notes['state'];
     }
     switch ($state) {
         case -1:
             // getConfig has not been configured asking for channel to administer
             if ($type != 'Message' || empty($text)) {
                 $this->conversation->notes['state'] = -1;
                 $this->conversation->update();
                 $data['text'] = 'Insert the channel name: (@yourchannel)';
                 $data['reply_markup'] = new ReplyKeyBoardHide(['selective' => true]);
                 $result = Request::sendMessage($data);
                 break;
             }
             $this->conversation->notes['channel'] = $text;
             $this->conversation->notes['last_message_id'] = $message->getMessageId();
             // Jump to state 1
             goto insert;
             // no break
         // no break
         default:
         case 0:
             // getConfig has been configured choose channel
             if ($type != 'Message' || !in_array($text, $channels)) {
                 $this->conversation->notes['state'] = 0;
                 $this->conversation->update();
                 $keyboard = [];
                 foreach ($channels as $channel) {
                     $keyboard[] = [$channel];
                 }
                 $reply_keyboard_markup = new ReplyKeyboardMarkup(['keyboard' => $keyboard, 'resize_keyboard' => true, 'one_time_keyboard' => true, 'selective' => true]);
                 $data['reply_markup'] = $reply_keyboard_markup;
                 $data['text'] = 'Select a channel';
                 if ($type != 'Message' || !in_array($text, $channels)) {
                     $data['text'] = 'Select a channel from the keyboard:';
                 }
                 $result = Request::sendMessage($data);
                 break;
             }
             $this->conversation->notes['channel'] = $text;
             $this->conversation->notes['last_message_id'] = $message->getMessageId();
             // no break
         // no break
         case 1:
             insert:
             if ($this->conversation->notes['last_message_id'] == $message->getMessageId() || $type == 'Message' && empty($text)) {
                 $this->conversation->notes['state'] = 1;
                 $this->conversation->update();
                 $data['reply_markup'] = new ReplyKeyBoardHide(['selective' => true]);
                 $data['text'] = 'Insert the content you want to share: text, photo, audio...';
                 $result = Request::sendMessage($data);
                 break;
             }
             $this->conversation->notes['last_message_id'] = $message->getMessageId();
             $this->conversation->notes['message'] = $message->reflect();
             $this->conversation->notes['message_type'] = $type;
             // no break
         // no break
         case 2:
             if ($this->conversation->notes['last_message_id'] == $message->getMessageId() || !($text == 'Yes' || $text == 'No')) {
                 $this->conversation->notes['state'] = 2;
                 $this->conversation->update();
                 // Execute this just with object that allow caption
                 if ($this->conversation->notes['message_type'] == 'Video' || $this->conversation->notes['message_type'] == 'Photo') {
                     $keyboard = [['Yes', 'No']];
                     $reply_keyboard_markup = new ReplyKeyboardMarkup(['keyboard' => $keyboard, 'resize_keyboard' => true, 'one_time_keyboard' => true, 'selective' => true]);
                     $data['reply_markup'] = $reply_keyboard_markup;
                     $data['text'] = 'Would you insert caption?';
                     if ($this->conversation->notes['last_message_id'] != $message->getMessageId() && !($text == 'Yes' || $text == 'No')) {
                         $data['text'] = 'Would you insert a caption?' . "\n" . 'Type Yes or No';
                     }
                     $result = Request::sendMessage($data);
                     break;
                 }
             }
             $this->conversation->notes['set_caption'] = false;
             if ($text == 'Yes') {
                 $this->conversation->notes['set_caption'] = true;
             }
             $this->conversation->notes['last_message_id'] = $message->getMessageId();
             // no break
         // no break
         case 3:
             if (($this->conversation->notes['last_message_id'] == $message->getMessageId() || $type != 'Message') && $this->conversation->notes['set_caption']) {
                 $this->conversation->notes['state'] = 3;
                 $this->conversation->update();
                 $data['text'] = 'Insert caption:';
                 $data['reply_markup'] = new ReplyKeyBoardHide(['selective' => true]);
                 $result = Request::sendMessage($data);
                 break;
             }
             $this->conversation->notes['last_message_id'] = $message->getMessageId();
             $this->conversation->notes['caption'] = $text;
             // no break
         // no break
         case 4:
             if ($this->conversation->notes['last_message_id'] == $message->getMessageId() || !($text == 'Yes' || $text == 'No')) {
                 $this->conversation->notes['state'] = 4;
                 $this->conversation->update();
                 $data['text'] = 'Message will look like this:';
                 $result = Request::sendMessage($data);
                 if ($this->conversation->notes['message_type'] != 'command') {
                     if ($this->conversation->notes['set_caption']) {
                         $data['caption'] = $this->conversation->notes['caption'];
                     }
                     $result = $this->sendBack(new Message($this->conversation->notes['message'], 'thisbot'), $data);
                     $data['text'] = 'Would you post it?';
                     if ($this->conversation->notes['last_message_id'] != $message->getMessageId() && !($text == 'Yes' || $text == 'No')) {
                         $data['text'] = 'Would you post it?' . "\n" . 'Press Yes or No';
                     }
                     $keyboard = [['Yes', 'No']];
                     $reply_keyboard_markup = new ReplyKeyboardMarkup(['keyboard' => $keyboard, 'resize_keyboard' => true, 'one_time_keyboard' => true, 'selective' => true]);
                     $data['reply_markup'] = $reply_keyboard_markup;
                     $result = Request::sendMessage($data);
                 }
                 break;
             }
             $this->conversation->notes['post_message'] = false;
             if ($text == 'Yes') {
                 $this->conversation->notes['post_message'] = true;
             }
             $this->conversation->notes['last_message_id'] = $message->getMessageId();
             // no break
         // no break
         case 5:
             $data['reply_markup'] = new ReplyKeyBoardHide(['selective' => true]);
             if ($this->conversation->notes['post_message']) {
                 $data['text'] = $this->publish(new Message($this->conversation->notes['message'], 'anystring'), $this->conversation->notes['channel'], $this->conversation->notes['caption']);
             } else {
                 $data['text'] = 'Abort by user, message not sent..';
             }
             $this->conversation->stop();
             $result = Request::sendMessage($data);
     }
     return $result;
 }
 /**
  * Command execute method
  *
  * @return \Longman\TelegramBot\Entities\ServerResponse|mixed
  * @throws \Longman\TelegramBot\Exception\TelegramException
  */
 public function execute()
 {
     $message = $this->getMessage();
     $chat_id = $message->getChat()->getId();
     $user_id = $message->getFrom()->getId();
     $type = $message->getType();
     // 'Cast' the command type into message to protect the machine state
     // if the commmad is recalled when the conversation is already started
     in_array($type, ['command', 'text'], true) && ($type = 'message');
     $text = trim($message->getText(true));
     $text_yes_or_no = $text === 'Yes' || $text === 'No';
     $data = ['chat_id' => $chat_id];
     // Conversation
     $this->conversation = new Conversation($user_id, $chat_id, $this->getName());
     $notes =& $this->conversation->notes;
     !is_array($notes) && ($notes = []);
     $channels = (array) $this->getConfig('your_channel');
     if (isset($notes['state'])) {
         $state = $notes['state'];
     } else {
         $state = count($channels) === 0 ? -1 : 0;
         $notes['last_message_id'] = $message->getMessageId();
     }
     switch ($state) {
         case -1:
             // getConfig has not been configured asking for channel to administer
             if ($type !== 'message' || $text === '') {
                 $notes['state'] = -1;
                 $this->conversation->update();
                 $data['text'] = 'Insert the channel name: (@yourchannel)';
                 $data['reply_markup'] = Keyboard::remove(['selective' => true]);
                 $result = Request::sendMessage($data);
                 break;
             }
             $notes['channel'] = $text;
             $notes['last_message_id'] = $message->getMessageId();
             // Jump to state 1
             goto insert;
             // no break
         // no break
         default:
         case 0:
             // getConfig has been configured choose channel
             if ($type !== 'message' || !in_array($text, $channels, true)) {
                 $notes['state'] = 0;
                 $this->conversation->update();
                 $keyboard = [];
                 foreach ($channels as $channel) {
                     $keyboard[] = [$channel];
                 }
                 $data['reply_markup'] = new Keyboard(['keyboard' => $keyboard, 'resize_keyboard' => true, 'one_time_keyboard' => true, 'selective' => true]);
                 $data['text'] = 'Select a channel from the keyboard:';
                 $result = Request::sendMessage($data);
                 break;
             }
             $notes['channel'] = $text;
             $notes['last_message_id'] = $message->getMessageId();
             // no break
         // no break
         case 1:
             insert:
             if ($type === 'message' && $text === '' || $notes['last_message_id'] === $message->getMessageId()) {
                 $notes['state'] = 1;
                 $this->conversation->update();
                 $data['reply_markup'] = Keyboard::remove(['selective' => true]);
                 $data['text'] = 'Insert the content you want to share: text, photo, audio...';
                 $result = Request::sendMessage($data);
                 break;
             }
             $notes['last_message_id'] = $message->getMessageId();
             $notes['message'] = $message->getRawData();
             $notes['message_type'] = $type;
             // no break
         // no break
         case 2:
             if (!$text_yes_or_no || $notes['last_message_id'] === $message->getMessageId()) {
                 $notes['state'] = 2;
                 $this->conversation->update();
                 // Execute this just with object that allow caption
                 if (in_array($notes['message_type'], ['video', 'photo'], true)) {
                     $data['reply_markup'] = new Keyboard(['keyboard' => [['Yes', 'No']], 'resize_keyboard' => true, 'one_time_keyboard' => true, 'selective' => true]);
                     $data['text'] = 'Would you like to insert a caption?';
                     if (!$text_yes_or_no && $notes['last_message_id'] !== $message->getMessageId()) {
                         $data['text'] .= PHP_EOL . 'Type Yes or No';
                     }
                     $result = Request::sendMessage($data);
                     break;
                 }
             }
             $notes['set_caption'] = $text === 'Yes';
             $notes['last_message_id'] = $message->getMessageId();
             // no break
         // no break
         case 3:
             if ($notes['set_caption'] && ($notes['last_message_id'] === $message->getMessageId() || $type !== 'message')) {
                 $notes['state'] = 3;
                 $this->conversation->update();
                 $data['text'] = 'Insert caption:';
                 $data['reply_markup'] = Keyboard::remove(['selective' => true]);
                 $result = Request::sendMessage($data);
                 break;
             }
             $notes['last_message_id'] = $message->getMessageId();
             $notes['caption'] = $text;
             // no break
         // no break
         case 4:
             if (!$text_yes_or_no || $notes['last_message_id'] === $message->getMessageId()) {
                 $notes['state'] = 4;
                 $this->conversation->update();
                 $data['text'] = 'Message will look like this:';
                 $result = Request::sendMessage($data);
                 if ($notes['message_type'] !== 'command') {
                     if ($notes['set_caption']) {
                         $data['caption'] = $notes['caption'];
                     }
                     $this->sendBack(new Message($notes['message'], $this->telegram->getBotName()), $data);
                     $data['reply_markup'] = new Keyboard(['keyboard' => [['Yes', 'No']], 'resize_keyboard' => true, 'one_time_keyboard' => true, 'selective' => true]);
                     $data['text'] = 'Would you like to post it?';
                     if (!$text_yes_or_no && $notes['last_message_id'] !== $message->getMessageId()) {
                         $data['text'] .= PHP_EOL . 'Type Yes or No';
                     }
                     $result = Request::sendMessage($data);
                 }
                 break;
             }
             $notes['post_message'] = $text === 'Yes';
             $notes['last_message_id'] = $message->getMessageId();
             // no break
         // no break
         case 5:
             $data['reply_markup'] = Keyboard::remove(['selective' => true]);
             if ($notes['post_message']) {
                 $data['text'] = $this->publish(new Message($notes['message'], $this->telegram->getBotName()), $notes['channel'], $notes['caption']);
             } else {
                 $data['text'] = 'Abort by user, message not sent..';
             }
             $this->conversation->stop();
             $result = Request::sendMessage($data);
     }
     return $result;
 }