· 6 years ago · Feb 08, 2020, 06:44 AM
1<?php
2
3/**
4 * This file is part of the TelegramBot package.
5 *
6 * (c) Avtandil Kikabidze aka LONGMAN <akalongman@gmail.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Longman\TelegramBot;
13
14defined('TB_BASE_PATH') || define('TB_BASE_PATH', __DIR__);
15defined('TB_BASE_COMMANDS_PATH') || define('TB_BASE_COMMANDS_PATH', TB_BASE_PATH . '/Commands');
16
17use Exception;
18use Longman\TelegramBot\Commands\Command;
19use Longman\TelegramBot\Entities\ServerResponse;
20use Longman\TelegramBot\Entities\Update;
21use Longman\TelegramBot\Exception\TelegramException;
22use PDO;
23use RecursiveDirectoryIterator;
24use RecursiveIteratorIterator;
25use RegexIterator;
26
27class Telegram
28{
29 /**
30 * Version
31 *
32 * @var string
33 */
34 protected $version = '0.61.1';
35
36 /**
37 * Telegram API key
38 *
39 * @var string
40 */
41 protected $api_key = '';
42
43 /**
44 * Telegram Bot username
45 *
46 * @var string
47 */
48 protected $bot_username = '';
49
50 /**
51 * Telegram Bot id
52 *
53 * @var string
54 */
55 protected $bot_id = '';
56
57 /**
58 * Raw request data (json) for webhook methods
59 *
60 * @var string
61 */
62 protected $input;
63
64 /**
65 * Custom commands paths
66 *
67 * @var array
68 */
69 protected $commands_paths = [];
70
71 /**
72 * Current Update object
73 *
74 * @var Update
75 */
76 protected $update;
77
78 /**
79 * Upload path
80 *
81 * @var string
82 */
83 protected $upload_path;
84
85 /**
86 * Download path
87 *
88 * @var string
89 */
90 protected $download_path;
91
92 /**
93 * MySQL integration
94 *
95 * @var bool
96 */
97 protected $mysql_enabled = false;
98
99 /**
100 * PDO object
101 *
102 * @var PDO
103 */
104 protected $pdo;
105
106 /**
107 * Commands config
108 *
109 * @var array
110 */
111 protected $commands_config = [];
112
113 /**
114 * Admins list
115 *
116 * @var array
117 */
118 protected $admins_list = [];
119
120 /**
121 * Users Permitted list
122 *
123 * @var array
124 */
125 protected $permitted_list = [];
126
127 /**
128 * All Users Permitted
129 *
130 * @var bool
131 */
132 protected $permitted_all = true;
133
134 /**
135 * ServerResponse of the last Command execution
136 *
137 * @var ServerResponse
138 */
139 protected $last_command_response;
140
141 /**
142 * Check if runCommands() is running in this session
143 *
144 * @var bool
145 */
146 protected $run_commands = false;
147
148 /**
149 * Is running getUpdates without DB enabled
150 *
151 * @var bool
152 */
153 protected $getupdates_without_database = false;
154
155 /**
156 * Last update ID
157 * Only used when running getUpdates without a database
158 *
159 * @var integer
160 */
161 protected $last_update_id = null;
162
163 /**
164 * Telegram constructor.
165 *
166 * @param string $api_key
167 * @param string $bot_username
168 *
169 * @throws TelegramException
170 */
171 public function __construct($api_key, $bot_username = '')
172 {
173 if (empty($api_key)) {
174 throw new TelegramException('API KEY not defined!');
175 }
176 preg_match('/(\d+)\:[\w\-]+/', $api_key, $matches);
177 if (!isset($matches[1])) {
178 throw new TelegramException('Invalid API KEY defined!');
179 }
180 $this->bot_id = $matches[1];
181 $this->api_key = $api_key;
182
183 if (!empty($bot_username)) {
184 $this->bot_username = $bot_username;
185 }
186
187 //Add default system commands path
188 $this->addCommandsPath(TB_BASE_COMMANDS_PATH . '/SystemCommands');
189
190 Request::initialize($this);
191 }
192
193 /**
194 * Initialize Database connection
195 *
196 * @param array $credential
197 * @param string $table_prefix
198 * @param string $encoding
199 *
200 * @return Telegram
201 * @throws TelegramException
202 */
203 public function enableMySql(array $credential, $table_prefix = null, $encoding = 'utf8mb4')
204 {
205 $this->pdo = DB::initialize($credential, $this, $table_prefix, $encoding);
206 ConversationDB::initializeConversation();
207 $this->mysql_enabled = true;
208
209 return $this;
210 }
211
212 /**
213 * Initialize Database external connection
214 *
215 * @param PDO $external_pdo_connection PDO database object
216 * @param string $table_prefix
217 *
218 * @return Telegram
219 * @throws TelegramException
220 */
221 public function enableExternalMySql($external_pdo_connection, $table_prefix = null)
222 {
223 $this->pdo = DB::externalInitialize($external_pdo_connection, $this, $table_prefix);
224 ConversationDB::initializeConversation();
225 $this->mysql_enabled = true;
226
227 return $this;
228 }
229
230 /**
231 * Get commands list
232 *
233 * @return array $commands
234 * @throws TelegramException
235 */
236 public function getCommandsList()
237 {
238 $commands = [];
239 foreach ($this->commands_paths as $path) {
240 try {
241 //Get all "*Command.php" files
242 $files = new RegexIterator(
243 new RecursiveIteratorIterator(
244 new RecursiveDirectoryIterator($path)
245 ),
246 '/^.+Command.php$/'
247 );
248
249 foreach ($files as $file) {
250 //Remove "Command.php" from filename
251 $command = $this->sanitizeCommand(substr($file->getFilename(), 0, -11));
252 $command_name = strtolower($command);
253
254 if (array_key_exists($command_name, $commands)) {
255 continue;
256 }
257
258 require_once $file->getPathname();
259
260 $command_obj = $this->getCommandObject($command);
261 if ($command_obj instanceof Command) {
262 $commands[$command_name] = $command_obj;
263 }
264 }
265 } catch (Exception $e) {
266 throw new TelegramException('Error getting commands from path: ' . $path);
267 }
268 }
269
270 return $commands;
271 }
272
273 /**
274 * Get an object instance of the passed command
275 *
276 * @param string $command
277 *
278 * @return Command|null
279 */
280 public function getCommandObject($command)
281 {
282 $which = ['System'];
283 $this->isAdmin() && $which[] = 'Admin';
284 //$which[] = 'User';
285 $this->isUserPermitted() && $which[] = 'User';
286
287 foreach ($which as $auth) {
288 $command_namespace = __NAMESPACE__ . '\\Commands\\' . $auth . 'Commands\\' . $this->ucfirstUnicode($command) . 'Command';
289 if (class_exists($command_namespace)) {
290 return new $command_namespace($this, $this->update);
291 }
292 }
293
294 return null;
295 }
296
297 /**
298 * Set custom input string for debug purposes
299 *
300 * @param string $input (json format)
301 *
302 * @return Telegram
303 */
304 public function setCustomInput($input)
305 {
306 $this->input = $input;
307
308 return $this;
309 }
310
311 /**
312 * Get custom input string for debug purposes
313 *
314 * @return string
315 */
316 public function getCustomInput()
317 {
318 return $this->input;
319 }
320
321 /**
322 * Get the ServerResponse of the last Command execution
323 *
324 * @return ServerResponse
325 */
326 public function getLastCommandResponse()
327 {
328 return $this->last_command_response;
329 }
330
331 /**
332 * Handle getUpdates method
333 *
334 * @param int|null $limit
335 * @param int|null $timeout
336 *
337 * @return ServerResponse
338 * @throws TelegramException
339 */
340 public function handleGetUpdates($limit = null, $timeout = null)
341 {
342 if (empty($this->bot_username)) {
343 throw new TelegramException('Bot Username is not defined!');
344 }
345
346 if (!DB::isDbConnected() && !$this->getupdates_without_database) {
347 return new ServerResponse(
348 [
349 'ok' => false,
350 'description' => 'getUpdates needs MySQL connection! (This can be overridden - see documentation)',
351 ],
352 $this->bot_username
353 );
354 }
355
356 $offset = 0;
357
358 //Take custom input into account.
359 if ($custom_input = $this->getCustomInput()) {
360 $response = new ServerResponse(json_decode($custom_input, true), $this->bot_username);
361 } else {
362 if (DB::isDbConnected() && $last_update = DB::selectTelegramUpdate(1)) {
363 //Get last update id from the database
364 $last_update = reset($last_update);
365
366 $this->last_update_id = isset($last_update['id']) ? $last_update['id'] : null;
367 }
368
369 if ($this->last_update_id !== null) {
370 $offset = $this->last_update_id + 1; //As explained in the telegram bot API documentation
371 }
372
373 $response = Request::getUpdates(
374 [
375 'offset' => $offset,
376 'limit' => $limit,
377 'timeout' => $timeout,
378 ]
379 );
380 }
381
382 if ($response->isOk()) {
383 $results = $response->getResult();
384
385 //Process all updates
386 /** @var Update $result */
387 foreach ($results as $result) {
388 $this->processUpdate($result);
389 }
390
391 if (!DB::isDbConnected() && !$custom_input && $this->last_update_id !== null && $offset === 0) {
392 //Mark update(s) as read after handling
393 Request::getUpdates(
394 [
395 'offset' => $this->last_update_id + 1,
396 'limit' => 1,
397 'timeout' => $timeout,
398 ]
399 );
400 }
401 }
402
403 return $response;
404 }
405
406 /**
407 * Handle bot request from webhook
408 *
409 * @return bool
410 *
411 * @throws TelegramException
412 */
413 public function handle()
414 {
415 if (empty($this->bot_username)) {
416 throw new TelegramException('Bot Username is not defined!');
417 }
418
419 $this->input = Request::getInput();
420
421 if (empty($this->input)) {
422 throw new TelegramException('Input is empty!');
423 }
424
425 $post = json_decode($this->input, true);
426 if (empty($post)) {
427 throw new TelegramException('Invalid JSON!');
428 }
429
430 if ($response = $this->processUpdate(new Update($post, $this->bot_username))) {
431 return $response->isOk();
432 }
433
434 return false;
435 }
436
437 /**
438 * Get the command name from the command type
439 *
440 * @param string $type
441 *
442 * @return string
443 */
444 protected function getCommandFromType($type)
445 {
446 return $this->ucfirstUnicode(str_replace('_', '', $type));
447 }
448
449 /**
450 * Process bot Update request
451 *
452 * @param Update $update
453 *
454 * @return ServerResponse
455 * @throws TelegramException
456 */
457 public function processUpdate(Update $update)
458 {
459 $this->update = $update;
460 $this->last_update_id = $update->getUpdateId();
461
462 //Load admin commands
463 if ($this->isAdmin()) {
464 $this->addCommandsPath(TB_BASE_COMMANDS_PATH . '/AdminCommands', false);
465 }
466
467 //Make sure we have an up-to-date command list
468 //This is necessary to "require" all the necessary command files!
469 $this->getCommandsList();
470
471 //If all else fails, it's a generic message.
472 $command = 'genericmessage';
473
474 $update_type = $this->update->getUpdateType();
475 if ($update_type === 'message') {
476 $message = $this->update->getMessage();
477 $type = $message->getType();
478
479 // Let's check if the message object has the type field we're looking for...
480 $command_tmp = $type === 'command' ? $message->getCommand() : $this->getCommandFromType($type);
481 // ...and if a fitting command class is available.
482 $command_obj = $this->getCommandObject($command_tmp);
483
484 // Empty usage string denotes a non-executable command.
485 // @see https://github.com/php-telegram-bot/core/issues/772#issuecomment-388616072
486 if (
487 ($command_obj === null && $type === 'command')
488 || ($command_obj !== null && $command_obj->getUsage() !== '')
489 ) {
490 $command = $command_tmp;
491 }
492 } else {
493 $command = $this->getCommandFromType($update_type);
494 }
495
496 //Make sure we don't try to process update that was already processed
497 $last_id = DB::selectTelegramUpdate(1, $this->update->getUpdateId());
498 if ($last_id && count($last_id) === 1) {
499 TelegramLog::debug('Duplicate update received, processing aborted!');
500 return Request::emptyResponse();
501 }
502
503 DB::insertRequest($this->update);
504
505 return ($this->isUserPermitted()) ? $this->executeCommand($command) : Request::sendMessage([
506 'chat_id'=>$message->getChat()->getId(),
507 'text'=>"Unauthorized access!",
508 'reply_to_message_id'=>$message->getMessageId()
509 ]);
510 }
511
512
513 /**
514 * Execute /command
515 *
516 * @param string $command
517 *
518 * @return ServerResponse
519 * @throws TelegramException
520 */
521 public function executeCommand($command)
522 {
523 $command = strtolower($command);
524 $command_obj = $this->getCommandObject($command);
525
526 if (!$command_obj || !$command_obj->isEnabled()) {
527 //Failsafe in case the Generic command can't be found
528 if ($command === 'generic') {
529 throw new TelegramException('Generic command missing!');
530 }
531
532 //Handle a generic command or non existing one
533 $this->last_command_response = $this->executeCommand('generic');
534 } else {
535 //execute() method is executed after preExecute()
536 //This is to prevent executing a DB query without a valid connection
537 $this->last_command_response = $command_obj->preExecute();
538 }
539
540 return $this->last_command_response;
541 }
542
543 /**
544 * Sanitize Command
545 *
546 * @param string $command
547 *
548 * @return string
549 */
550 protected function sanitizeCommand($command)
551 {
552 return str_replace(' ', '', $this->ucwordsUnicode(str_replace('_', ' ', $command)));
553 }
554
555 /**
556 * Enable a single Admin account
557 *
558 * @param integer $admin_id Single admin id
559 *
560 * @return Telegram
561 */
562 public function enableAdmin($admin_id)
563 {
564 if (!is_int($admin_id) || $admin_id <= 0) {
565 TelegramLog::error('Invalid value "' . $admin_id . '" for admin.');
566 } elseif (!in_array($admin_id, $this->admins_list, true)) {
567 $this->admins_list[] = $admin_id;
568 }
569
570 return $this;
571 }
572
573 /**
574 * Enable a single Permitted account
575 *
576 * @param integer $permited_id Single permitted id
577 *
578 * @return Telegram
579 */
580 public function enablePermitted($permitted_id)
581 {
582 if (!is_int($permitted_id) || $permitted_id <= 0) {
583 TelegramLog::error('Invalid value "' . $permitted_id . '" for permitted.');
584 } elseif (!in_array($permitted_id, $this->permitted_list, true)) {
585 $this->permitted_list[] = $permitted_id;
586 }
587 return $this;
588 }
589
590 /**
591 * Enable a list of Admin Accounts
592 *
593 * @param array $admin_ids List of admin ids
594 *
595 * @return Telegram
596 */
597 public function enableAdmins(array $admin_ids)
598 {
599 foreach ($admin_ids as $admin_id) {
600 $this->enableAdmin($admin_id);
601 }
602
603 return $this;
604 }
605
606 /**
607 * Enable a list of Permitted Accounts
608 *
609 * @param array $permitted_ids List of permitted ids
610 *
611 * @return Telegram
612 */
613 public function enablePermitteds(array $permitted_ids)
614 {
615 if (!empty($permitted_ids)) {
616 $this->permitted_all = false;
617 foreach ($permitted_ids as $permitted_id) {
618 $this->enablePermitted($permitted_id);
619 }
620 }
621 return $this;
622 }
623
624 /**
625 * Get list of admins
626 *
627 * @return array
628 */
629 public function getAdminList()
630 {
631 return $this->admins_list;
632 }
633
634 /**
635 * Get list of permitted
636 *
637 * @return array
638 */
639 public function getPermittedList()
640 {
641 return $this->permitted_list;
642 }
643
644 /**
645 * Check if the passed user is an admin
646 *
647 * If no user id is passed, the current update is checked for a valid message sender.
648 *
649 * @param int|null $user_id
650 *
651 * @return bool
652 */
653 public function isAdmin($user_id = null)
654 {
655 if ($user_id === null && $this->update !== null) {
656 //Try to figure out if the user is an admin
657 $update_methods = [
658 'getMessage',
659 'getEditedMessage',
660 'getChannelPost',
661 'getEditedChannelPost',
662 'getInlineQuery',
663 'getChosenInlineResult',
664 'getCallbackQuery',
665 ];
666 foreach ($update_methods as $update_method) {
667 $object = call_user_func([$this->update, $update_method]);
668 if ($object !== null && $from = $object->getFrom()) {
669 $user_id = $from->getId();
670 break;
671 }
672 }
673 }
674
675 return ($user_id === null) ? false : in_array($user_id, $this->admins_list, true);
676 }
677
678 /**
679 * Check if the passed user is an permitted
680 *
681 * If no user id is passed, the current update is checked for a valid message sender.
682 *
683 * @param int|null $user_id
684 *
685 * @return bool
686 */
687 public function isUserPermitted($user_id = null)
688 {
689 if ($user_id === null && $this->update !== null) {
690 //Try to figure out if the user is an permitted
691 $update_methods = [
692 'getMessage',
693 'getEditedMessage',
694 'getChannelPost',
695 'getEditedChannelPost',
696 'getInlineQuery',
697 'getChosenInlineResult',
698 'getCallbackQuery',
699 ];
700 foreach ($update_methods as $update_method) {
701 $object = call_user_func([$this->update, $update_method]);
702 if ($object !== null && $from = $object->getFrom()) {
703 $user_id = $from->getId();
704 break;
705 }
706 }
707 }
708
709 return ($user_id === null) ? false : ($this->permitted_all) ? true : in_array($user_id, $this->permitted_list, true);
710 }
711
712 /**
713 * Check if user required the db connection
714 *
715 * @return bool
716 */
717 public function isDbEnabled()
718 {
719 if ($this->mysql_enabled) {
720 return true;
721 } else {
722 return false;
723 }
724 }
725
726 /**
727 * Add a single custom commands path
728 *
729 * @param string $path Custom commands path to add
730 * @param bool $before If the path should be prepended or appended to the list
731 *
732 * @return Telegram
733 */
734 public function addCommandsPath($path, $before = true)
735 {
736 if (!is_dir($path)) {
737 TelegramLog::error('Commands path "' . $path . '" does not exist.');
738 } elseif (!in_array($path, $this->commands_paths, true)) {
739 if ($before) {
740 array_unshift($this->commands_paths, $path);
741 } else {
742 $this->commands_paths[] = $path;
743 }
744 }
745
746 return $this;
747 }
748
749 /**
750 * Add multiple custom commands paths
751 *
752 * @param array $paths Custom commands paths to add
753 * @param bool $before If the paths should be prepended or appended to the list
754 *
755 * @return Telegram
756 */
757 public function addCommandsPaths(array $paths, $before = true)
758 {
759 foreach ($paths as $path) {
760 $this->addCommandsPath($path, $before);
761 }
762
763 return $this;
764 }
765
766 /**
767 * Return the list of commands paths
768 *
769 * @return array
770 */
771 public function getCommandsPaths()
772 {
773 return $this->commands_paths;
774 }
775
776 /**
777 * Set custom upload path
778 *
779 * @param string $path Custom upload path
780 *
781 * @return Telegram
782 */
783 public function setUploadPath($path)
784 {
785 $this->upload_path = $path;
786
787 return $this;
788 }
789
790 /**
791 * Get custom upload path
792 *
793 * @return string
794 */
795 public function getUploadPath()
796 {
797 return $this->upload_path;
798 }
799
800 /**
801 * Set custom download path
802 *
803 * @param string $path Custom download path
804 *
805 * @return Telegram
806 */
807 public function setDownloadPath($path)
808 {
809 $this->download_path = $path;
810
811 return $this;
812 }
813
814 /**
815 * Get custom download path
816 *
817 * @return string
818 */
819 public function getDownloadPath()
820 {
821 return $this->download_path;
822 }
823
824 /**
825 * Set command config
826 *
827 * Provide further variables to a particular commands.
828 * For example you can add the channel name at the command /sendtochannel
829 * Or you can add the api key for external service.
830 *
831 * @param string $command
832 * @param array $config
833 *
834 * @return Telegram
835 */
836 public function setCommandConfig($command, array $config)
837 {
838 $this->commands_config[$command] = $config;
839
840 return $this;
841 }
842
843 /**
844 * Get command config
845 *
846 * @param string $command
847 *
848 * @return array
849 */
850 public function getCommandConfig($command)
851 {
852 return isset($this->commands_config[$command]) ? $this->commands_config[$command] : [];
853 }
854
855 /**
856 * Get API key
857 *
858 * @return string
859 */
860 public function getApiKey()
861 {
862 return $this->api_key;
863 }
864
865 /**
866 * Get Bot name
867 *
868 * @return string
869 */
870 public function getBotUsername()
871 {
872 return $this->bot_username;
873 }
874
875 /**
876 * Get Bot Id
877 *
878 * @return string
879 */
880 public function getBotId()
881 {
882 return $this->bot_id;
883 }
884
885 /**
886 * Get Version
887 *
888 * @return string
889 */
890 public function getVersion()
891 {
892 return $this->version;
893 }
894
895 /**
896 * Set Webhook for bot
897 *
898 * @param string $url
899 * @param array $data Optional parameters.
900 *
901 * @return ServerResponse
902 * @throws TelegramException
903 */
904 public function setWebhook($url, array $data = [])
905 {
906 if (empty($url)) {
907 throw new TelegramException('Hook url is empty!');
908 }
909
910 $data = array_intersect_key($data, array_flip([
911 'certificate',
912 'max_connections',
913 'allowed_updates',
914 ]));
915 $data['url'] = $url;
916
917 // If the certificate is passed as a path, encode and add the file to the data array.
918 if (!empty($data['certificate']) && is_string($data['certificate'])) {
919 $data['certificate'] = Request::encodeFile($data['certificate']);
920 }
921
922 $result = Request::setWebhook($data);
923
924 if (!$result->isOk()) {
925 throw new TelegramException(
926 'Webhook was not set! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
927 );
928 }
929
930 return $result;
931 }
932
933 /**
934 * Delete any assigned webhook
935 *
936 * @return mixed
937 * @throws TelegramException
938 */
939 public function deleteWebhook()
940 {
941 $result = Request::deleteWebhook();
942
943 if (!$result->isOk()) {
944 throw new TelegramException(
945 'Webhook was not deleted! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
946 );
947 }
948
949 return $result;
950 }
951
952 /**
953 * Replace function `ucwords` for UTF-8 characters in the class definition and commands
954 *
955 * @param string $str
956 * @param string $encoding (default = 'UTF-8')
957 *
958 * @return string
959 */
960 protected function ucwordsUnicode($str, $encoding = 'UTF-8')
961 {
962 return mb_convert_case($str, MB_CASE_TITLE, $encoding);
963 }
964
965 /**
966 * Replace function `ucfirst` for UTF-8 characters in the class definition and commands
967 *
968 * @param string $str
969 * @param string $encoding (default = 'UTF-8')
970 *
971 * @return string
972 */
973 protected function ucfirstUnicode($str, $encoding = 'UTF-8')
974 {
975 return mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding)
976 . mb_strtolower(mb_substr($str, 1, mb_strlen($str), $encoding), $encoding);
977 }
978
979 /**
980 * Enable requests limiter
981 *
982 * @param array $options
983 *
984 * @return Telegram
985 * @throws TelegramException
986 */
987 public function enableLimiter(array $options = [])
988 {
989 Request::setLimiter(true, $options);
990
991 return $this;
992 }
993
994 /**
995 * Run provided commands
996 *
997 * @param array $commands
998 *
999 * @throws TelegramException
1000 */
1001 public function runCommands($commands)
1002 {
1003 if (!is_array($commands) || empty($commands)) {
1004 throw new TelegramException('No command(s) provided!');
1005 }
1006
1007 $this->run_commands = true;
1008
1009 $result = Request::getMe();
1010
1011 if ($result->isOk()) {
1012 $result = $result->getResult();
1013
1014 $bot_id = $result->getId();
1015 $bot_name = $result->getFirstName();
1016 $bot_username = $result->getUsername();
1017 } else {
1018 $bot_id = $this->getBotId();
1019 $bot_name = $this->getBotUsername();
1020 $bot_username = $this->getBotUsername();
1021 }
1022
1023
1024 $this->enableAdmin($bot_id); // Give bot access to admin commands
1025 $this->getCommandsList(); // Load full commands list
1026
1027 foreach ($commands as $command) {
1028 $this->update = new Update(
1029 [
1030 'update_id' => 0,
1031 'message' => [
1032 'message_id' => 0,
1033 'from' => [
1034 'id' => $bot_id,
1035 'first_name' => $bot_name,
1036 'username' => $bot_username,
1037 ],
1038 'date' => time(),
1039 'chat' => [
1040 'id' => $bot_id,
1041 'type' => 'private',
1042 ],
1043 'text' => $command,
1044 ],
1045 ]
1046 );
1047
1048 $this->executeCommand($this->update->getMessage()->getCommand());
1049 }
1050 }
1051
1052 /**
1053 * Is this session initiated by runCommands()
1054 *
1055 * @return bool
1056 */
1057 public function isRunCommands()
1058 {
1059 return $this->run_commands;
1060 }
1061
1062 /**
1063 * Switch to enable running getUpdates without a database
1064 *
1065 * @param bool $enable
1066 */
1067 public function useGetUpdatesWithoutDatabase($enable = true)
1068 {
1069 $this->getupdates_without_database = $enable;
1070 }
1071
1072 /**
1073 * Return last update id
1074 *
1075 * @return int
1076 */
1077 public function getLastUpdateId()
1078 {
1079 return $this->last_update_id;
1080 }
1081}