Completed
Push — 772-simple_prevent_system_comm... ( 4ac954 )
by Armando
03:31
created

Telegram::isDbEnabled()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 6
1
<?php
2
/**
3
 * This file is part of the TelegramBot package.
4
 *
5
 * (c) Avtandil Kikabidze aka LONGMAN <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Longman\TelegramBot;
12
13 1
defined('TB_BASE_PATH') || define('TB_BASE_PATH', __DIR__);
14 1
defined('TB_BASE_COMMANDS_PATH') || define('TB_BASE_COMMANDS_PATH', TB_BASE_PATH . '/Commands');
15
16
use Exception;
17
use Longman\TelegramBot\Commands\Command;
18
use Longman\TelegramBot\Entities\ServerResponse;
19
use Longman\TelegramBot\Entities\Update;
20
use Longman\TelegramBot\Exception\TelegramException;
21
use PDO;
22
use RecursiveDirectoryIterator;
23
use RecursiveIteratorIterator;
24
use RegexIterator;
25
26
class Telegram
27
{
28
    /**
29
     * Version
30
     *
31
     * @var string
32
     */
33
    protected $version = '0.57.0';
34
35
    /**
36
     * Telegram API key
37
     *
38
     * @var string
39
     */
40
    protected $api_key = '';
41
42
    /**
43
     * Telegram Bot username
44
     *
45
     * @var string
46
     */
47
    protected $bot_username = '';
48
49
    /**
50
     * Telegram Bot id
51
     *
52
     * @var string
53
     */
54
    protected $bot_id = '';
55
56
    /**
57
     * Raw request data (json) for webhook methods
58
     *
59
     * @var string
60
     */
61
    protected $input;
62
63
    /**
64
     * Custom commands paths
65
     *
66
     * @var array
67
     */
68
    protected $commands_paths = [];
69
70
    /**
71
     * Current Update object
72
     *
73
     * @var \Longman\TelegramBot\Entities\Update
74
     */
75
    protected $update;
76
77
    /**
78
     * Upload path
79
     *
80
     * @var string
81
     */
82
    protected $upload_path;
83
84
    /**
85
     * Download path
86
     *
87
     * @var string
88
     */
89
    protected $download_path;
90
91
    /**
92
     * MySQL integration
93
     *
94
     * @var boolean
95
     */
96
    protected $mysql_enabled = false;
97
98
    /**
99
     * PDO object
100
     *
101
     * @var \PDO
102
     */
103
    protected $pdo;
104
105
    /**
106
     * Commands config
107
     *
108
     * @var array
109
     */
110
    protected $commands_config = [];
111
112
    /**
113
     * Admins list
114
     *
115
     * @var array
116
     */
117
    protected $admins_list = [];
118
119
    /**
120
     * ServerResponse of the last Command execution
121
     *
122
     * @var \Longman\TelegramBot\Entities\ServerResponse
123
     */
124
    protected $last_command_response;
125
126
    /**
127
     * Check if runCommands() is running in this session
128
     *
129
     * @var boolean
130
     */
131
    protected $run_commands = false;
132
133
    /**
134
     * Is running getUpdates without DB enabled
135
     *
136
     * @var bool
137
     */
138
    protected $getupdates_without_database = false;
139
140
    /**
141
     * Last update ID
142
     * Only used when running getUpdates without a database
143
     *
144
     * @var integer
145
     */
146
    protected $last_update_id = null;
147
148
    /**
149
     * Telegram constructor.
150
     *
151
     * @param string $api_key
152
     * @param string $bot_username
153
     *
154
     * @throws \Longman\TelegramBot\Exception\TelegramException
155
     */
156 30
    public function __construct($api_key, $bot_username = '')
157
    {
158 30
        if (empty($api_key)) {
159 1
            throw new TelegramException('API KEY not defined!');
160
        }
161 30
        preg_match('/(\d+)\:[\w\-]+/', $api_key, $matches);
162 30
        if (!isset($matches[1])) {
163 1
            throw new TelegramException('Invalid API KEY defined!');
164
        }
165 30
        $this->bot_id  = $matches[1];
166 30
        $this->api_key = $api_key;
167
168 30
        if (!empty($bot_username)) {
169 30
            $this->bot_username = $bot_username;
170
        }
171
172
        //Add default system commands path
173 30
        $this->addCommandsPath(TB_BASE_COMMANDS_PATH . '/SystemCommands');
174
175 30
        Request::initialize($this);
176 30
    }
177
178
    /**
179
     * Initialize Database connection
180
     *
181
     * @param array  $credential
182
     * @param string $table_prefix
183
     * @param string $encoding
184
     *
185
     * @return \Longman\TelegramBot\Telegram
186
     * @throws \Longman\TelegramBot\Exception\TelegramException
187
     */
188 9 View Code Duplication
    public function enableMySql(array $credential, $table_prefix = null, $encoding = 'utf8mb4')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
189
    {
190 9
        $this->pdo = DB::initialize($credential, $this, $table_prefix, $encoding);
191 9
        ConversationDB::initializeConversation();
192 9
        $this->mysql_enabled = true;
193
194 9
        return $this;
195
    }
196
197
    /**
198
     * Initialize Database external connection
199
     *
200
     * @param PDO    $external_pdo_connection PDO database object
201
     * @param string $table_prefix
202
     *
203
     * @return \Longman\TelegramBot\Telegram
204
     * @throws \Longman\TelegramBot\Exception\TelegramException
205
     */
206 View Code Duplication
    public function enableExternalMySql($external_pdo_connection, $table_prefix = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
207
    {
208
        $this->pdo = DB::externalInitialize($external_pdo_connection, $this, $table_prefix);
209
        ConversationDB::initializeConversation();
210
        $this->mysql_enabled = true;
211
212
        return $this;
213
    }
214
215
    /**
216
     * Get commands list
217
     *
218
     * @return array $commands
219
     * @throws \Longman\TelegramBot\Exception\TelegramException
220
     */
221 1
    public function getCommandsList()
222
    {
223 1
        $commands = [];
224
225 1
        foreach ($this->commands_paths as $path) {
226
            try {
227
                //Get all "*Command.php" files
228 1
                $files = new RegexIterator(
229 1
                    new RecursiveIteratorIterator(
230 1
                        new RecursiveDirectoryIterator($path)
231
                    ),
232 1
                    '/^.+Command.php$/'
233
                );
234
235 1
                foreach ($files as $file) {
236
                    //Remove "Command.php" from filename
237 1
                    $command      = $this->sanitizeCommand(substr($file->getFilename(), 0, -11));
238 1
                    $command_name = strtolower($command);
239
240 1
                    if (array_key_exists($command_name, $commands)) {
241
                        continue;
242
                    }
243
244 1
                    require_once $file->getPathname();
245
246 1
                    $command_obj = $this->getCommandObject($command);
247 1
                    if ($command_obj instanceof Command) {
248 1
                        $commands[$command_name] = $command_obj;
249
                    }
250
                }
251
            } catch (Exception $e) {
252
                throw new TelegramException('Error getting commands from path: ' . $path);
253
            }
254
        }
255
256 1
        return $commands;
257
    }
258
259
    /**
260
     * Get an object instance of the passed command
261
     *
262
     * @param string $command
263
     *
264
     * @return \Longman\TelegramBot\Commands\Command|null
265
     */
266 1
    public function getCommandObject($command)
267
    {
268 1
        $which = ['System'];
269 1
        $this->isAdmin() && $which[] = 'Admin';
270 1
        $which[] = 'User';
271
272 1
        foreach ($which as $auth) {
273 1
            $command_namespace = __NAMESPACE__ . '\\Commands\\' . $auth . 'Commands\\' . $this->ucfirstUnicode($command) . 'Command';
274 1
            if (class_exists($command_namespace)) {
275 1
                return new $command_namespace($this, $this->update);
276
            }
277
        }
278
279
        return null;
280
    }
281
282
    /**
283
     * Set custom input string for debug purposes
284
     *
285
     * @param string $input (json format)
286
     *
287
     * @return \Longman\TelegramBot\Telegram
288
     */
289
    public function setCustomInput($input)
290
    {
291
        $this->input = $input;
292
293
        return $this;
294
    }
295
296
    /**
297
     * Get custom input string for debug purposes
298
     *
299
     * @return string
300
     */
301
    public function getCustomInput()
302
    {
303
        return $this->input;
304
    }
305
306
    /**
307
     * Get the ServerResponse of the last Command execution
308
     *
309
     * @return \Longman\TelegramBot\Entities\ServerResponse
310
     */
311
    public function getLastCommandResponse()
312
    {
313
        return $this->last_command_response;
314
    }
315
316
    /**
317
     * Handle getUpdates method
318
     *
319
     * @param int|null $limit
320
     * @param int|null $timeout
321
     *
322
     * @return \Longman\TelegramBot\Entities\ServerResponse
323
     * @throws \Longman\TelegramBot\Exception\TelegramException
324
     */
325
    public function handleGetUpdates($limit = null, $timeout = null)
326
    {
327
        if (empty($this->bot_username)) {
328
            throw new TelegramException('Bot Username is not defined!');
329
        }
330
331
        if (!DB::isDbConnected() && !$this->getupdates_without_database) {
332
            return new ServerResponse(
333
                [
334
                    'ok'          => false,
335
                    'description' => 'getUpdates needs MySQL connection! (This can be overridden - see documentation)',
336
                ],
337
                $this->bot_username
338
            );
339
        }
340
341
        $offset = 0;
342
343
        //Take custom input into account.
344
        if ($custom_input = $this->getCustomInput()) {
345
            $response = new ServerResponse(json_decode($custom_input, true), $this->bot_username);
346
        } else {
347
            if (DB::isDbConnected()) {
348
                //Get last update id from the database
349
                $last_update = DB::selectTelegramUpdate(1);
350
                $last_update = reset($last_update);
351
352
                $this->last_update_id = isset($last_update['id']) ? $last_update['id'] : null;
353
            }
354
355
            if ($this->last_update_id !== null) {
356
                $offset = $this->last_update_id + 1;    //As explained in the telegram bot API documentation
357
            }
358
359
            $response = Request::getUpdates(
360
                [
361
                    'offset'  => $offset,
362
                    'limit'   => $limit,
363
                    'timeout' => $timeout,
364
                ]
365
            );
366
        }
367
368
        if ($response->isOk()) {
369
            $results = $response->getResult();
370
371
            //Process all updates
372
            /** @var Update $result */
373
            foreach ($results as $result) {
374
                $this->processUpdate($result);
375
            }
376
377
            if (!DB::isDbConnected() && !$custom_input && $this->last_update_id !== null && $offset === 0) {
378
                //Mark update(s) as read after handling
379
                Request::getUpdates(
380
                    [
381
                        'offset'  => $this->last_update_id + 1,
382
                        'limit'   => 1,
383
                        'timeout' => $timeout,
384
                    ]
385
                );
386
            }
387
        }
388
389
        return $response;
390
    }
391
392
    /**
393
     * Handle bot request from webhook
394
     *
395
     * @return bool
396
     *
397
     * @throws \Longman\TelegramBot\Exception\TelegramException
398
     */
399
    public function handle()
400
    {
401
        if (empty($this->bot_username)) {
402
            throw new TelegramException('Bot Username is not defined!');
403
        }
404
405
        $this->input = Request::getInput();
406
407
        if (empty($this->input)) {
408
            throw new TelegramException('Input is empty!');
409
        }
410
411
        $post = json_decode($this->input, true);
412
        if (empty($post)) {
413
            throw new TelegramException('Invalid JSON!');
414
        }
415
416
        if ($response = $this->processUpdate(new Update($post, $this->bot_username))) {
417
            return $response->isOk();
418
        }
419
420
        return false;
421
    }
422
423
    /**
424
     * Get the command name from the command type
425
     *
426
     * @param string $type
427
     *
428
     * @return string
429
     */
430
    protected function getCommandFromType($type)
431
    {
432
        return $this->ucfirstUnicode(str_replace('_', '', $type));
433
    }
434
435
    /**
436
     * Process bot Update request
437
     *
438
     * @param \Longman\TelegramBot\Entities\Update $update
439
     *
440
     * @return \Longman\TelegramBot\Entities\ServerResponse
441
     * @throws \Longman\TelegramBot\Exception\TelegramException
442
     */
443
    public function processUpdate(Update $update)
444
    {
445
        $this->update = $update;
446
        $this->last_update_id = $update->getUpdateId();
447
448
        //Load admin commands
449
        if ($this->isAdmin()) {
450
            $this->addCommandsPath(TB_BASE_COMMANDS_PATH . '/AdminCommands', false);
451
        }
452
453
        //Make sure we have an up-to-date command list
454
        //This is necessary to "require" all the necessary command files!
455
        $this->getCommandsList();
456
457
        //If all else fails, it's a generic message.
458
        $command = 'genericmessage';
459
460
        $update_type = $this->update->getUpdateType();
461
        if ($update_type === 'message') {
462
            $message = $this->update->getMessage();
463
            $type    = $message->getType();
464
465
            // Let's check if the message object has the type field we're looking for...
466
            $command_tmp = $type === 'command' ? $message->getCommand() : $this->getCommandFromType($type);
467
            // ...and if a fitting command class is available.
468
            $command_obj = $this->getCommandObject($command_tmp);
469
470
            // Empty usage string denotes a non-executable command.
471
            // @see https://github.com/php-telegram-bot/core/issues/772#issuecomment-388616072
472
            if ($command_obj !== null && $command_obj->getUsage() !== '') {
473
                $command = $command_tmp;
474
            }
475
        } else {
476
            $command = $this->getCommandFromType($update_type);
477
        }
478
479
        //Make sure we don't try to process update that was already processed
480
        $last_id = DB::selectTelegramUpdate(1, $this->update->getUpdateId());
481
        if ($last_id && count($last_id) === 1) {
482
            TelegramLog::debug('Duplicate update received, processing aborted!');
483
            return Request::emptyResponse();
484
        }
485
486
        DB::insertRequest($this->update);
487
488
        return $this->executeCommand($command);
489
    }
490
491
    /**
492
     * Execute /command
493
     *
494
     * @param string $command
495
     *
496
     * @return mixed
497
     * @throws \Longman\TelegramBot\Exception\TelegramException
498
     */
499
    public function executeCommand($command)
500
    {
501
        $command     = strtolower($command);
502
        $command_obj = $this->getCommandObject($command);
503
504
        if (!$command_obj || !$command_obj->isEnabled()) {
505
            //Failsafe in case the Generic command can't be found
506
            if ($command === 'generic') {
507
                throw new TelegramException('Generic command missing!');
508
            }
509
510
            //Handle a generic command or non existing one
511
            $this->last_command_response = $this->executeCommand('generic');
512
        } else {
513
            //execute() method is executed after preExecute()
514
            //This is to prevent executing a DB query without a valid connection
515
            $this->last_command_response = $command_obj->preExecute();
516
        }
517
518
        return $this->last_command_response;
519
    }
520
521
    /**
522
     * Sanitize Command
523
     *
524
     * @param string $command
525
     *
526
     * @return string
527
     */
528 1
    protected function sanitizeCommand($command)
529
    {
530 1
        return str_replace(' ', '', $this->ucwordsUnicode(str_replace('_', ' ', $command)));
531
    }
532
533
    /**
534
     * Enable a single Admin account
535
     *
536
     * @param integer $admin_id Single admin id
537
     *
538
     * @return \Longman\TelegramBot\Telegram
539
     */
540 1
    public function enableAdmin($admin_id)
541
    {
542 1
        if (!is_int($admin_id) || $admin_id <= 0) {
543 1
            TelegramLog::error('Invalid value "%s" for admin.', $admin_id);
544 1
        } elseif (!in_array($admin_id, $this->admins_list, true)) {
545 1
            $this->admins_list[] = $admin_id;
546
        }
547
548 1
        return $this;
549
    }
550
551
    /**
552
     * Enable a list of Admin Accounts
553
     *
554
     * @param array $admin_ids List of admin ids
555
     *
556
     * @return \Longman\TelegramBot\Telegram
557
     */
558 1
    public function enableAdmins(array $admin_ids)
559
    {
560 1
        foreach ($admin_ids as $admin_id) {
561 1
            $this->enableAdmin($admin_id);
562
        }
563
564 1
        return $this;
565
    }
566
567
    /**
568
     * Get list of admins
569
     *
570
     * @return array
571
     */
572 1
    public function getAdminList()
573
    {
574 1
        return $this->admins_list;
575
    }
576
577
    /**
578
     * Check if the passed user is an admin
579
     *
580
     * If no user id is passed, the current update is checked for a valid message sender.
581
     *
582
     * @param int|null $user_id
583
     *
584
     * @return bool
585
     */
586 1
    public function isAdmin($user_id = null)
587
    {
588 1
        if ($user_id === null && $this->update !== null) {
589
            //Try to figure out if the user is an admin
590
            $update_methods = [
591
                'getMessage',
592
                'getEditedMessage',
593
                'getChannelPost',
594
                'getEditedChannelPost',
595
                'getInlineQuery',
596
                'getChosenInlineResult',
597
                'getCallbackQuery',
598
            ];
599
            foreach ($update_methods as $update_method) {
600
                $object = call_user_func([$this->update, $update_method]);
601
                if ($object !== null && $from = $object->getFrom()) {
602
                    $user_id = $from->getId();
603
                    break;
604
                }
605
            }
606
        }
607
608 1
        return ($user_id === null) ? false : in_array($user_id, $this->admins_list, true);
609
    }
610
611
    /**
612
     * Check if user required the db connection
613
     *
614
     * @return bool
615
     */
616
    public function isDbEnabled()
617
    {
618
        if ($this->mysql_enabled) {
619
            return true;
620
        } else {
621
            return false;
622
        }
623
    }
624
625
    /**
626
     * Add a single custom commands path
627
     *
628
     * @param string $path   Custom commands path to add
629
     * @param bool   $before If the path should be prepended or appended to the list
630
     *
631
     * @return \Longman\TelegramBot\Telegram
632
     */
633 30
    public function addCommandsPath($path, $before = true)
634
    {
635 30
        if (!is_dir($path)) {
636 1
            TelegramLog::error('Commands path "%s" does not exist.', $path);
637 30
        } elseif (!in_array($path, $this->commands_paths, true)) {
638 30
            if ($before) {
639 30
                array_unshift($this->commands_paths, $path);
640
            } else {
641
                $this->commands_paths[] = $path;
642
            }
643
        }
644
645 30
        return $this;
646
    }
647
648
    /**
649
     * Add multiple custom commands paths
650
     *
651
     * @param array $paths  Custom commands paths to add
652
     * @param bool  $before If the paths should be prepended or appended to the list
653
     *
654
     * @return \Longman\TelegramBot\Telegram
655
     */
656 1
    public function addCommandsPaths(array $paths, $before = true)
657
    {
658 1
        foreach ($paths as $path) {
659 1
            $this->addCommandsPath($path, $before);
660
        }
661
662 1
        return $this;
663
    }
664
665
    /**
666
     * Return the list of commands paths
667
     *
668
     * @return array
669
     */
670 1
    public function getCommandsPaths()
671
    {
672 1
        return $this->commands_paths;
673
    }
674
675
    /**
676
     * Set custom upload path
677
     *
678
     * @param string $path Custom upload path
679
     *
680
     * @return \Longman\TelegramBot\Telegram
681
     */
682
    public function setUploadPath($path)
683
    {
684
        $this->upload_path = $path;
685
686
        return $this;
687
    }
688
689
    /**
690
     * Get custom upload path
691
     *
692
     * @return string
693
     */
694
    public function getUploadPath()
695
    {
696
        return $this->upload_path;
697
    }
698
699
    /**
700
     * Set custom download path
701
     *
702
     * @param string $path Custom download path
703
     *
704
     * @return \Longman\TelegramBot\Telegram
705
     */
706
    public function setDownloadPath($path)
707
    {
708
        $this->download_path = $path;
709
710
        return $this;
711
    }
712
713
    /**
714
     * Get custom download path
715
     *
716
     * @return string
717
     */
718
    public function getDownloadPath()
719
    {
720
        return $this->download_path;
721
    }
722
723
    /**
724
     * Set command config
725
     *
726
     * Provide further variables to a particular commands.
727
     * For example you can add the channel name at the command /sendtochannel
728
     * Or you can add the api key for external service.
729
     *
730
     * @param string $command
731
     * @param array  $config
732
     *
733
     * @return \Longman\TelegramBot\Telegram
734
     */
735 14
    public function setCommandConfig($command, array $config)
736
    {
737 14
        $this->commands_config[$command] = $config;
738
739 14
        return $this;
740
    }
741
742
    /**
743
     * Get command config
744
     *
745
     * @param string $command
746
     *
747
     * @return array
748
     */
749 15
    public function getCommandConfig($command)
750
    {
751 15
        return isset($this->commands_config[$command]) ? $this->commands_config[$command] : [];
752
    }
753
754
    /**
755
     * Get API key
756
     *
757
     * @return string
758
     */
759 1
    public function getApiKey()
760
    {
761 1
        return $this->api_key;
762
    }
763
764
    /**
765
     * Get Bot name
766
     *
767
     * @return string
768
     */
769 1
    public function getBotUsername()
770
    {
771 1
        return $this->bot_username;
772
    }
773
774
    /**
775
     * Get Bot Id
776
     *
777
     * @return string
778
     */
779
    public function getBotId()
780
    {
781
        return $this->bot_id;
782
    }
783
784
    /**
785
     * Get Version
786
     *
787
     * @return string
788
     */
789
    public function getVersion()
790
    {
791
        return $this->version;
792
    }
793
794
    /**
795
     * Set Webhook for bot
796
     *
797
     * @param string $url
798
     * @param array  $data Optional parameters.
799
     *
800
     * @return \Longman\TelegramBot\Entities\ServerResponse
801
     * @throws \Longman\TelegramBot\Exception\TelegramException
802
     */
803
    public function setWebhook($url, array $data = [])
804
    {
805
        if (empty($url)) {
806
            throw new TelegramException('Hook url is empty!');
807
        }
808
809
        $data        = array_intersect_key($data, array_flip([
810
            'certificate',
811
            'max_connections',
812
            'allowed_updates',
813
        ]));
814
        $data['url'] = $url;
815
816
        // If the certificate is passed as a path, encode and add the file to the data array.
817
        if (!empty($data['certificate']) && is_string($data['certificate'])) {
818
            $data['certificate'] = Request::encodeFile($data['certificate']);
819
        }
820
821
        $result = Request::setWebhook($data);
822
823 View Code Duplication
        if (!$result->isOk()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
824
            throw new TelegramException(
825
                'Webhook was not set! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
826
            );
827
        }
828
829
        return $result;
830
    }
831
832
    /**
833
     * Delete any assigned webhook
834
     *
835
     * @return mixed
836
     * @throws \Longman\TelegramBot\Exception\TelegramException
837
     */
838
    public function deleteWebhook()
839
    {
840
        $result = Request::deleteWebhook();
841
842 View Code Duplication
        if (!$result->isOk()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
843
            throw new TelegramException(
844
                'Webhook was not deleted! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
845
            );
846
        }
847
848
        return $result;
849
    }
850
851
    /**
852
     * Replace function `ucwords` for UTF-8 characters in the class definition and commands
853
     *
854
     * @param string $str
855
     * @param string $encoding (default = 'UTF-8')
856
     *
857
     * @return string
858
     */
859 1
    protected function ucwordsUnicode($str, $encoding = 'UTF-8')
860
    {
861 1
        return mb_convert_case($str, MB_CASE_TITLE, $encoding);
862
    }
863
864
    /**
865
     * Replace function `ucfirst` for UTF-8 characters in the class definition and commands
866
     *
867
     * @param string $str
868
     * @param string $encoding (default = 'UTF-8')
869
     *
870
     * @return string
871
     */
872 1
    protected function ucfirstUnicode($str, $encoding = 'UTF-8')
873
    {
874 1
        return mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding)
875 1
               . mb_strtolower(mb_substr($str, 1, mb_strlen($str), $encoding), $encoding);
876
    }
877
878
    /**
879
     * Enable requests limiter
880
     *
881
     * @param  array $options
882
     *
883
     * @return \Longman\TelegramBot\Telegram
884
     */
885
    public function enableLimiter(array $options = [])
886
    {
887
        Request::setLimiter(true, $options);
888
889
        return $this;
890
    }
891
892
    /**
893
     * Run provided commands
894
     *
895
     * @param array $commands
896
     *
897
     * @throws TelegramException
898
     */
899
    public function runCommands($commands)
900
    {
901
        if (!is_array($commands) || empty($commands)) {
902
            throw new TelegramException('No command(s) provided!');
903
        }
904
905
        $this->run_commands  = true;
906
907
        $result = Request::getMe();
908
909
        if ($result->isOk()) {
910
            $result = $result->getResult();
911
912
            $bot_id       = $result->getId();
913
            $bot_name     = $result->getFirstName();
914
            $bot_username = $result->getUsername();
915
        } else {
916
            $bot_id       = $this->getBotId();
917
            $bot_name     = $this->getBotUsername();
918
            $bot_username = $this->getBotUsername();
919
        }
920
921
922
        $this->enableAdmin($bot_id);    // Give bot access to admin commands
923
        $this->getCommandsList();       // Load full commands list
924
925
        foreach ($commands as $command) {
926
            $this->update = new Update(
927
                [
928
                    'update_id' => 0,
929
                    'message'   => [
930
                        'message_id' => 0,
931
                        'from'       => [
932
                            'id'         => $bot_id,
933
                            'first_name' => $bot_name,
934
                            'username'   => $bot_username,
935
                        ],
936
                        'date'       => time(),
937
                        'chat'       => [
938
                            'id'   => $bot_id,
939
                            'type' => 'private',
940
                        ],
941
                        'text'       => $command,
942
                    ],
943
                ]
944
            );
945
946
            $this->executeCommand($this->update->getMessage()->getCommand());
947
        }
948
    }
949
950
    /**
951
     * Is this session initiated by runCommands()
952
     *
953
     * @return bool
954
     */
955
    public function isRunCommands()
956
    {
957
        return $this->run_commands;
958
    }
959
960
    /**
961
     * Switch to enable running getUpdates without a database
962
     *
963
     * @param bool $enable
964
     */
965
    public function useGetUpdatesWithoutDatabase($enable = true)
966
    {
967
        $this->getupdates_without_database = $enable;
968
    }
969
970
    /**
971
     * Return last update id
972
     *
973
     * @return int
974
     */
975
    public function getLastUpdateId()
976
    {
977
        return $this->last_update_id;
978
    }
979
}
980