GenericmessageCommand.php :
<?php
namespace Longman\TelegramBot\Commands\SystemCommands;
use Longman\TelegramBot\Commands\SystemCommand;
use Longman\TelegramBot\Commands\UserCommands\AllCoursesCommand;
use Longman\TelegramBot\Commands\UserCommands\RegisterCoursesCommand;
use Longman\TelegramBot\Entities\Update;
use Longman\TelegramBot\Request;
class GenericmessageCommand extends SystemCommand
{
protected $name = 'Genericmessage';
protected $description = 'Handle generic message';
protected $version = '1.0.0';
public function execute()
{
$text = trim($this->getMessage()->getText(true));
$update = json_decode($this->update->toJson(), true);
if ($text === 'All Courses') {
$update['message']['text'] = '/all_courses';
return (new AllCoursesCommand($this->telegram, new Update($update)))->preExecute();
} elseif ($text === 'Register') {
$update['message']['text'] = '/register_courses';
return (new RegisterCoursesCommand($this->telegram, new Update($update)))->preExecute();
}
return Request::emptyResponse();
}
}
In RegisterCoursesCommand.php I want to response 'What is your name?!' then parse the user message, then response 'What is your age?!' then parse user age (message) and ...
How to do that?!
Check out the /survey command.
You can copy that, rename it to RegisterCoursesCommand and then adjust the code.
Thank you for your reply, but it works just for the first property ("Type your name:") and when I response, bot does not send me the next question!
You have the database set up? Conversations require a database connection.
It still doesn't work !! :(
Here is all of my codes:
hook.php :
<?php
// Load composer
require __DIR__ . '/vendor/autoload.php';
use Longman\TelegramBot\Telegram;
use Longman\TelegramBot\TelegramLog;
use Longman\TelegramBot\Exception\TelegramException;
// Bot's API key and name
$bot_api_key = '************';
$bot_username = '************';
// Define all paths for custom commands
$commands_folder = __DIR__ . '/Commands/';
$mysql_credentials = [
'host' => 'localhost',
'user' => '************',
'password' => '************',
'database' => '************',
];
try {
// Create Telegram API object
$telegram = new Telegram($bot_api_key, $bot_username);
// Add commands paths containing custom commands
$telegram->addCommandsPath($commands_folder);
// Logging (Error, Debug and Raw Updates)
TelegramLog::initErrorLog(__DIR__ . "/{$bot_username}_error.log");
TelegramLog::initDebugLog(__DIR__ . "/{$bot_username}_debug.log");
TelegramLog::initUpdateLog(__DIR__ . "/{$bot_username}_update.log");
// Set custom Upload and Download paths
$telegram->setDownloadPath(__DIR__ . '/Download');
$telegram->setUploadPath(__DIR__ . '/Upload');
// Requests Limiter (tries to prevent reaching Telegram API limits)
$telegram->enableLimiter();
$telegram->enableMySQL($mysql_credentials);
// Handle telegram webhook request
$telegram->handle();
} catch (TelegramException $e) {
TelegramLog::error($e);
}
RegisterCoursesCommand.php :
<?php
namespace Longman\TelegramBot\Commands\UserCommands;
use Longman\TelegramBot\Commands\UserCommand;
use Longman\TelegramBot\Conversation;
use Longman\TelegramBot\Entities\Keyboard;
use Longman\TelegramBot\Request;
/**
* User "/survey" command
*/
class RegisterCoursesCommand extends UserCommand
{
/**
* @var string
*/
protected $name = 'register_courses';
/**
* @var string
*/
protected $description = 'Register courses';
/**
* @var string
*/
protected $usage = '/register_courses';
/**
* @var string
*/
protected $version = '1.0.0';
/**
* @var bool
*/
protected $need_mysql = true;
/**
* Conversation Object
*
* @var \Longman\TelegramBot\Conversation
*/
protected $conversation;
/**
* Command execute method
*
* @return \Longman\TelegramBot\Entities\ServerResponse
* @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'] = 'Name: ';
$data['reply_markup'] = Keyboard::remove(['selective' => true]);
$result = Request::sendMessage($data);
break;
}
$notes['name'] = $text;
$text = '';
// no break
case 1:
if ($text === '' || !is_numeric($text)) {
$notes['state'] = 1;
$this->conversation->update();
$data['text'] = 'National ID Card NO: ';
if ($text !== '') {
$data['text'] = 'It must be numeric!';
}
$result = Request::sendMessage($data);
break;
}
$notes['N_ID_C'] = $text;
$text = '';
// no break
case 2:
if ($text === '') {
$notes['state'] = 2;
$this->conversation->update();
$data['text'] = 'Courses :';
$result = Request::sendMessage($data);
break;
}
$notes['courses'] = $text;
$text = '';
// no break
case 3:
// This field is optional
$notes['state'] = 3;
$this->conversation->update();
$data['text'] = 'Grade :';
$result = Request::sendMessage($data);
$notes['grade'] = $text;
break;
// no break
case 4:
// This field is optional
$notes['state'] = 4;
$this->conversation->update();
$data['text'] = 'School :';
$result = Request::sendMessage($data);
$notes['school'] = $text;
break;
// no break
case 5:
if ($text === '' || !is_numeric($text)) {
$notes['state'] = 5;
$this->conversation->update();
$data['text'] = 'Phone :';
if ($text !== '') {
$data['text'] = 'It must be numeric!';
}
$result = Request::sendMessage($data);
break;
}
$notes['phone'] = $text;
// no break
case 6:
if ($text === '' || !filter_var($text, FILTER_VALIDATE_EMAIL)) {
$notes['state'] = 6;
$this->conversation->update();
$data['text'] = 'Email :';
if ($text !== '') {
$data['text'] = 'Email is not valid!';
}
$result = Request::sendMessage($data);
break;
}
$notes['email'] = $text;
// no break
case 7:
$this->conversation->update();
$out_text = 'Result :' . PHP_EOL;
unset($notes['state']);
foreach ($notes as $k => $v) {
$out_text .= PHP_EOL . ucfirst($k) . ': ' . $v;
}
$data['text'] = $out_text;
$this->conversation->stop();
$result = Request::sendMessage($data);
break;
}
return $result;
}
}
GenericmessageCommand.php :
<?php
namespace Longman\TelegramBot\Commands\SystemCommands;
use Longman\TelegramBot\Commands\SystemCommand;
use Longman\TelegramBot\Commands\UserCommands\AllCoursesCommand;
use Longman\TelegramBot\Commands\UserCommands\RegisterCoursesCommand;
use Longman\TelegramBot\Entities\Update;
use Longman\TelegramBot\Request;
class GenericmessageCommand extends SystemCommand
{
protected $name = 'Genericmessage';
protected $description = 'Handle generic message';
protected $version = '1.0.0';
public function execute()
{
$text = trim($this->getMessage()->getText(true));
$update = json_decode($this->update->toJson(), true);
if ($text === 'All Courses') {
$update['message']['text'] = '/all_courses';
return (new AllCoursesCommand($this->telegram, new Update($update)))->preExecute();
} elseif ($text === 'Register') {
$update['message']['text'] = '/register_courses';
return (new RegisterCoursesCommand($this->telegram, new Update($update)))->preExecute();
}
return Request::emptyResponse();
}
}
Right, there are a few things that need changing in your code, but it's quite easy 馃槂
Because the filename and class name are linked to the command name, your class must also have the _ in it. I know that's very unpretty, but unfortunately that's just how it works for now 馃槙
Commands with an underscore in their name aren't fully supported at the moment, as certain internal code isn't designed for them. So it's more of a hack...
I hope we have a better solution for all command names in the future!
So your command files would be Register_coursesCommand.php and All_coursesCommand.php, class names the same, just without the .php.
Then, inside your GenericmessageCommand class, you still need to handle conversations, otherwise the bot doesn't know that there is a current conversation happening.
So your GenericmessageCommand::execute() method should be like this:
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);
}
$text = trim($this->getMessage()->getText(true));
$update = json_decode($this->update->toJson(), true);
if ($text === 'All Courses') {
$update['message']['text'] = '/all_courses';
return (new All_coursesCommand($this->telegram, new Update($update)))->preExecute();
} elseif ($text === 'Register') {
$update['message']['text'] = '/register_courses';
return (new Register_coursesCommand($this->telegram, new Update($update)))->preExecute();
}
return Request::emptyResponse();
}
Alternatively, you could also create a simple /courses command, which then could show a keyboard with a few buttons, Show All, Register, etc.
Yes It worked!
Thank you so much !!
Most helpful comment
Right, there are a few things that need changing in your code, but it's quite easy 馃槂
Because the filename and class name are linked to the command name, your class must also have the
_in it. I know that's very unpretty, but unfortunately that's just how it works for now 馃槙Commands with an underscore in their name aren't fully supported at the moment, as certain internal code isn't designed for them. So it's more of a hack...
I hope we have a better solution for all command names in the future!
So your command files would be
Register_coursesCommand.phpandAll_coursesCommand.php, class names the same, just without the.php.Then, inside your
GenericmessageCommandclass, you still need to handle conversations, otherwise the bot doesn't know that there is a current conversation happening.So your
GenericmessageCommand::execute()method should be like this:Alternatively, you could also create a simple
/coursescommand, which then could show a keyboard with a few buttons,Show All,Register, etc.