Completed
Push — bot_api_3.0 ( 6b3f71...bb0bf5 )
by Armando
03:38
created

Telegram::isRunCommands()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
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
define('BASE_PATH', __DIR__);
14 1
define('BASE_COMMANDS_PATH', 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.44.1';
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
     * Botan.io integration
128
     *
129
     * @var boolean
130
     */
131
    protected $botan_enabled = false;
132
133
    /**
134
     * Check if runCommands() is running in this session
135
     *
136
     * @var boolean
137
     */
138
    protected $run_commands = false;
139
140
    /**
141
     * Telegram constructor.
142
     *
143
     * @param string $api_key
144
     * @param string $bot_username
145
     *
146
     * @throws \Longman\TelegramBot\Exception\TelegramException
147
     */
148 30
    public function __construct($api_key, $bot_username = '')
149
    {
150 30
        if (empty($api_key)) {
151 1
            throw new TelegramException('API KEY not defined!');
152
        }
153 30
        preg_match('/(\d+)\:[\w\-]+/', $api_key, $matches);
154 30
        if (!isset($matches[1])) {
155 1
            throw new TelegramException('Invalid API KEY defined!');
156
        }
157 30
        $this->bot_id  = $matches[1];
158 30
        $this->api_key = $api_key;
159
160 30
        if (!empty($bot_username)) {
161 30
            $this->bot_username = $bot_username;
162
        }
163
164
        //Add default system commands path
165 30
        $this->addCommandsPath(BASE_COMMANDS_PATH . '/SystemCommands');
166
167 30
        Request::initialize($this);
168 30
    }
169
170
    /**
171
     * Initialize Database connection
172
     *
173
     * @param array  $credential
174
     * @param string $table_prefix
175
     * @param string $encoding
176
     *
177
     * @return \Longman\TelegramBot\Telegram
178
     * @throws \Longman\TelegramBot\Exception\TelegramException
179
     */
180 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...
181
    {
182 9
        $this->pdo = DB::initialize($credential, $this, $table_prefix, $encoding);
183 9
        ConversationDB::initializeConversation();
184 9
        $this->mysql_enabled = true;
185
186 9
        return $this;
187
    }
188
189
    /**
190
     * Initialize Database external connection
191
     *
192
     * @param PDO    $external_pdo_connection PDO database object
193
     * @param string $table_prefix
194
     *
195
     * @return \Longman\TelegramBot\Telegram
196
     * @throws \Longman\TelegramBot\Exception\TelegramException
197
     */
198 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...
199
    {
200
        $this->pdo = DB::externalInitialize($external_pdo_connection, $this, $table_prefix);
201
        ConversationDB::initializeConversation();
202
        $this->mysql_enabled = true;
203
204
        return $this;
205
    }
206
207
    /**
208
     * Get commands list
209
     *
210
     * @return array $commands
211
     * @throws \Longman\TelegramBot\Exception\TelegramException
212
     */
213 1
    public function getCommandsList()
214
    {
215 1
        $commands = [];
216
217 1
        foreach ($this->commands_paths as $path) {
218
            try {
219
                //Get all "*Command.php" files
220 1
                $files = new RegexIterator(
221 1
                    new RecursiveIteratorIterator(
222 1
                        new RecursiveDirectoryIterator($path)
223
                    ),
224 1
                    '/^.+Command.php$/'
225
                );
226
227 1
                foreach ($files as $file) {
228
                    //Remove "Command.php" from filename
229 1
                    $command      = $this->sanitizeCommand(substr($file->getFilename(), 0, -11));
230 1
                    $command_name = strtolower($command);
231
232 1
                    if (array_key_exists($command_name, $commands)) {
233
                        continue;
234
                    }
235
236 1
                    require_once $file->getPathname();
237
238 1
                    $command_obj = $this->getCommandObject($command);
239 1
                    if ($command_obj instanceof Command) {
240 1
                        $commands[$command_name] = $command_obj;
241
                    }
242
                }
243
            } catch (Exception $e) {
244
                throw new TelegramException('Error getting commands from path: ' . $path);
245
            }
246
        }
247
248 1
        return $commands;
249
    }
250
251
    /**
252
     * Get an object instance of the passed command
253
     *
254
     * @param string $command
255
     *
256
     * @return \Longman\TelegramBot\Commands\Command|null
257
     */
258 1
    public function getCommandObject($command)
259
    {
260 1
        $which = ['System'];
261 1
        $this->isAdmin() && $which[] = 'Admin';
262 1
        $which[] = 'User';
263
264 1
        foreach ($which as $auth) {
265 1
            $command_namespace = __NAMESPACE__ . '\\Commands\\' . $auth . 'Commands\\' . $this->ucfirstUnicode($command) . 'Command';
266 1
            if (class_exists($command_namespace)) {
267 1
                return new $command_namespace($this, $this->update);
268
            }
269
        }
270
271
        return null;
272
    }
273
274
    /**
275
     * Set custom input string for debug purposes
276
     *
277
     * @param string $input (json format)
278
     *
279
     * @return \Longman\TelegramBot\Telegram
280
     */
281
    public function setCustomInput($input)
282
    {
283
        $this->input = $input;
284
285
        return $this;
286
    }
287
288
    /**
289
     * Get custom input string for debug purposes
290
     *
291
     * @return string
292
     */
293
    public function getCustomInput()
294
    {
295
        return $this->input;
296
    }
297
298
    /**
299
     * Get the ServerResponse of the last Command execution
300
     *
301
     * @return \Longman\TelegramBot\Entities\ServerResponse
302
     */
303
    public function getLastCommandResponse()
304
    {
305
        return $this->last_command_response;
306
    }
307
308
    /**
309
     * Handle getUpdates method
310
     *
311
     * @param int|null $limit
312
     * @param int|null $timeout
313
     *
314
     * @return \Longman\TelegramBot\Entities\ServerResponse
315
     * @throws \Longman\TelegramBot\Exception\TelegramException
316
     */
317
    public function handleGetUpdates($limit = null, $timeout = null)
318
    {
319
        if (empty($this->bot_username)) {
320
            throw new TelegramException('Bot Username is not defined!');
321
        }
322
323
        if (!DB::isDbConnected()) {
324
            return new ServerResponse(
325
                [
326
                    'ok'          => false,
327
                    'description' => 'getUpdates needs MySQL connection!',
328
                ],
329
                $this->bot_username
330
            );
331
        }
332
333
        //DB Query
334
        $last_update = DB::selectTelegramUpdate(1);
335
        $last_update = reset($last_update);
336
337
        //As explained in the telegram bot api documentation
338
        $offset = isset($last_update['id']) ? $last_update['id'] + 1 : null;
339
340
        $response = Request::getUpdates(
341
            [
342
                'offset'  => $offset,
343
                'limit'   => $limit,
344
                'timeout' => $timeout,
345
            ]
346
        );
347
348
        if ($response->isOk()) {
349
            //Process all updates
350
            /** @var Update $result */
351
            foreach ((array) $response->getResult() as $result) {
352
                $this->processUpdate($result);
353
            }
354
        }
355
356
        return $response;
357
    }
358
359
    /**
360
     * Handle bot request from webhook
361
     *
362
     * @return bool
363
     *
364
     * @throws \Longman\TelegramBot\Exception\TelegramException
365
     */
366
    public function handle()
367
    {
368
        if (empty($this->bot_username)) {
369
            throw new TelegramException('Bot Username is not defined!');
370
        }
371
372
        $this->input = Request::getInput();
373
374
        if (empty($this->input)) {
375
            throw new TelegramException('Input is empty!');
376
        }
377
378
        $post = json_decode($this->input, true);
379
        if (empty($post)) {
380
            throw new TelegramException('Invalid JSON!');
381
        }
382
383
        if ($response = $this->processUpdate(new Update($post, $this->bot_username))) {
384
            return $response->isOk();
385
        }
386
387
        return false;
388
    }
389
390
    /**
391
     * Get the command name from the command type
392
     *
393
     * @param string $type
394
     *
395
     * @return string
396
     */
397
    protected function getCommandFromType($type)
398
    {
399
        return $this->ucfirstUnicode(str_replace('_', '', $type));
400
    }
401
402
    /**
403
     * Process bot Update request
404
     *
405
     * @param \Longman\TelegramBot\Entities\Update $update
406
     *
407
     * @return \Longman\TelegramBot\Entities\ServerResponse
408
     * @throws \Longman\TelegramBot\Exception\TelegramException
409
     */
410
    public function processUpdate(Update $update)
411
    {
412
        $this->update = $update;
413
414
        //If all else fails, it's a generic message.
415
        $command = 'genericmessage';
416
417
        $update_type = $this->update->getUpdateType();
418
        if (in_array($update_type, ['edited_message', 'channel_post', 'edited_channel_post', 'inline_query', 'chosen_inline_result', 'callback_query'], true)) {
419
            $command = $this->getCommandFromType($update_type);
420
        } elseif ($update_type === 'message') {
421
            $message = $this->update->getMessage();
422
423
            //Load admin commands
424
            if ($this->isAdmin()) {
425
                $this->addCommandsPath(BASE_COMMANDS_PATH . '/AdminCommands', false);
426
            }
427
428
            $type = $message->getType();
429
            if ($type === 'command') {
430
                $command = $message->getCommand();
431
            } elseif (in_array($type, [
432
                'channel_chat_created',
433
                'delete_chat_photo',
434
                'group_chat_created',
435
                'left_chat_member',
436
                'migrate_from_chat_id',
437
                'migrate_to_chat_id',
438
                'new_chat_member',
439
                'new_chat_photo',
440
                'new_chat_title',
441
                'pinned_message',
442
                'supergroup_chat_created',
443
            ], true)
444
            ) {
445
                $command = $this->getCommandFromType($type);
446
            }
447
        }
448
449
        //Make sure we have an up-to-date command list
450
        //This is necessary to "require" all the necessary command files!
451
        $this->getCommandsList();
452
453
        DB::insertRequest($this->update);
454
455
        return $this->executeCommand($command);
0 ignored issues
show
Bug introduced by
It seems like $command defined by $message->getCommand() on line 430 can also be of type boolean; however, Longman\TelegramBot\Telegram::executeCommand() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
456
    }
457
458
    /**
459
     * Execute /command
460
     *
461
     * @param string $command
462
     *
463
     * @return mixed
464
     * @throws \Longman\TelegramBot\Exception\TelegramException
465
     */
466
    public function executeCommand($command)
467
    {
468
        $command_obj = $this->getCommandObject($command);
469
470
        if (!$command_obj || !$command_obj->isEnabled()) {
471
            //Failsafe in case the Generic command can't be found
472
            if ($command === 'Generic') {
473
                throw new TelegramException('Generic command missing!');
474
            }
475
476
            //Handle a generic command or non existing one
477
            $this->last_command_response = $this->executeCommand('Generic');
478
        } else {
479
            //Botan.io integration, make sure only the actual command user executed is reported
480
            if ($this->botan_enabled) {
481
                Botan::lock($command);
482
            }
483
484
            //execute() method is executed after preExecute()
485
            //This is to prevent executing a DB query without a valid connection
486
            $this->last_command_response = $command_obj->preExecute();
487
488
            //Botan.io integration, send report after executing the command
489
            if ($this->botan_enabled) {
490
                Botan::track($this->update, $command);
491
            }
492
        }
493
494
        return $this->last_command_response;
495
    }
496
497
    /**
498
     * Sanitize Command
499
     *
500
     * @param string $command
501
     *
502
     * @return string
503
     */
504 1
    protected function sanitizeCommand($command)
505
    {
506 1
        return str_replace(' ', '', $this->ucwordsUnicode(str_replace('_', ' ', $command)));
507
    }
508
509
    /**
510
     * Enable a single Admin account
511
     *
512
     * @param integer $admin_id Single admin id
513
     *
514
     * @return \Longman\TelegramBot\Telegram
515
     */
516 1
    public function enableAdmin($admin_id)
517
    {
518 1
        if (is_int($admin_id) && $admin_id > 0 && !in_array($admin_id, $this->admins_list, true)) {
519 1
            $this->admins_list[] = $admin_id;
520
        } else {
521 1
            TelegramLog::error('Invalid value "%s" for admin.', $admin_id);
522
        }
523
524 1
        return $this;
525
    }
526
527
    /**
528
     * Enable a list of Admin Accounts
529
     *
530
     * @param array $admin_ids List of admin ids
531
     *
532
     * @return \Longman\TelegramBot\Telegram
533
     */
534 1
    public function enableAdmins(array $admin_ids)
535
    {
536 1
        foreach ($admin_ids as $admin_id) {
537 1
            $this->enableAdmin($admin_id);
538
        }
539
540 1
        return $this;
541
    }
542
543
    /**
544
     * Get list of admins
545
     *
546
     * @return array
547
     */
548 1
    public function getAdminList()
549
    {
550 1
        return $this->admins_list;
551
    }
552
553
    /**
554
     * Check if the passed user is an admin
555
     *
556
     * If no user id is passed, the current update is checked for a valid message sender.
557
     *
558
     * @param int|null $user_id
559
     *
560
     * @return bool
561
     */
562 1
    public function isAdmin($user_id = null)
563
    {
564 1
        if ($user_id === null && $this->update !== null) {
565
            //Try to figure out if the user is an admin
566
            $update_methods = [
567
                'getMessage',
568
                'getEditedMessage',
569
                'getChannelPost',
570
                'getEditedChannelPost',
571
                'getInlineQuery',
572
                'getChosenInlineResult',
573
                'getCallbackQuery',
574
            ];
575
            foreach ($update_methods as $update_method) {
576
                $object = call_user_func([$this->update, $update_method]);
577
                if ($object !== null && $from = $object->getFrom()) {
578
                    $user_id = $from->getId();
579
                    break;
580
                }
581
            }
582
        }
583
584 1
        return ($user_id === null) ? false : in_array($user_id, $this->admins_list, true);
585
    }
586
587
    /**
588
     * Check if user required the db connection
589
     *
590
     * @return bool
591
     */
592
    public function isDbEnabled()
593
    {
594
        if ($this->mysql_enabled) {
595
            return true;
596
        } else {
597
            return false;
598
        }
599
    }
600
601
    /**
602
     * Add a single custom commands path
603
     *
604
     * @param string $path   Custom commands path to add
605
     * @param bool   $before If the path should be prepended or appended to the list
606
     *
607
     * @return \Longman\TelegramBot\Telegram
608
     */
609 30
    public function addCommandsPath($path, $before = true)
610
    {
611 30
        if (!is_dir($path)) {
612 1
            TelegramLog::error('Commands path "%s" does not exist.', $path);
613 30
        } elseif (!in_array($path, $this->commands_paths, true)) {
614 30
            if ($before) {
615 30
                array_unshift($this->commands_paths, $path);
616
            } else {
617
                $this->commands_paths[] = $path;
618
            }
619
        }
620
621 30
        return $this;
622
    }
623
624
    /**
625
     * Add multiple custom commands paths
626
     *
627
     * @param array $paths  Custom commands paths to add
628
     * @param bool  $before If the paths should be prepended or appended to the list
629
     *
630
     * @return \Longman\TelegramBot\Telegram
631
     */
632 1
    public function addCommandsPaths(array $paths, $before = true)
633
    {
634 1
        foreach ($paths as $path) {
635 1
            $this->addCommandsPath($path, $before);
636
        }
637
638 1
        return $this;
639
    }
640
641
    /**
642
     * Return the list of commands paths
643
     *
644
     * @return array
645
     */
646 1
    public function getCommandsPaths()
647
    {
648 1
        return $this->commands_paths;
649
    }
650
651
    /**
652
     * Set custom upload path
653
     *
654
     * @param string $path Custom upload path
655
     *
656
     * @return \Longman\TelegramBot\Telegram
657
     */
658
    public function setUploadPath($path)
659
    {
660
        $this->upload_path = $path;
661
662
        return $this;
663
    }
664
665
    /**
666
     * Get custom upload path
667
     *
668
     * @return string
669
     */
670
    public function getUploadPath()
671
    {
672
        return $this->upload_path;
673
    }
674
675
    /**
676
     * Set custom download path
677
     *
678
     * @param string $path Custom download path
679
     *
680
     * @return \Longman\TelegramBot\Telegram
681
     */
682
    public function setDownloadPath($path)
683
    {
684
        $this->download_path = $path;
685
686
        return $this;
687
    }
688
689
    /**
690
     * Get custom download path
691
     *
692
     * @return string
693
     */
694
    public function getDownloadPath()
695
    {
696
        return $this->download_path;
697
    }
698
699
    /**
700
     * Set command config
701
     *
702
     * Provide further variables to a particular commands.
703
     * For example you can add the channel name at the command /sendtochannel
704
     * Or you can add the api key for external service.
705
     *
706
     * @param string $command
707
     * @param array  $config
708
     *
709
     * @return \Longman\TelegramBot\Telegram
710
     */
711 14
    public function setCommandConfig($command, array $config)
712
    {
713 14
        $this->commands_config[$command] = $config;
714
715 14
        return $this;
716
    }
717
718
    /**
719
     * Get command config
720
     *
721
     * @param string $command
722
     *
723
     * @return array
724
     */
725 15
    public function getCommandConfig($command)
726
    {
727 15
        return isset($this->commands_config[$command]) ? $this->commands_config[$command] : [];
728
    }
729
730
    /**
731
     * Get API key
732
     *
733
     * @return string
734
     */
735 1
    public function getApiKey()
736
    {
737 1
        return $this->api_key;
738
    }
739
740
    /**
741
     * Get Bot name
742
     *
743
     * @return string
744
     */
745 1
    public function getBotUsername()
746
    {
747 1
        return $this->bot_username;
748
    }
749
750
    /**
751
     * Get Bot name
752
     *
753
     * @todo: Left for backwards compatibility, remove in the future
754
     *
755
     * @return string
756
     */
757
    public function getBotName()
758
    {
759
        TelegramLog::debug('Usage of deprecated method getBotName() detected, please use getBotUsername() instead!');
760
        return $this->getBotUsername();
761
    }
762
763
    /**
764
     * Get Bot Id
765
     *
766
     * @return string
767
     */
768
    public function getBotId()
769
    {
770
        return $this->bot_id;
771
    }
772
773
    /**
774
     * Get Version
775
     *
776
     * @return string
777
     */
778
    public function getVersion()
779
    {
780
        return $this->version;
781
    }
782
783
    /**
784
     * Set Webhook for bot
785
     *
786
     * @param string $url
787
     * @param array  $data Optional parameters.
788
     *
789
     * @return \Longman\TelegramBot\Entities\ServerResponse
790
     * @throws \Longman\TelegramBot\Exception\TelegramException
791
     */
792
    public function setWebhook($url, array $data = [])
793
    {
794
        if (empty($url)) {
795
            throw new TelegramException('Hook url is empty!');
796
        }
797
798
        $result = Request::setWebhook($url, $data);
799
800 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...
801
            throw new TelegramException(
802
                'Webhook was not set! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
803
            );
804
        }
805
806
        return $result;
807
    }
808
809
    /**
810
     * Deprecated alias for deleteWebhook
811
     *
812
     * This is kept for backwards compatibility!
813
     *
814
     * @return mixed
815
     * @throws \Longman\TelegramBot\Exception\TelegramException
816
     */
817
    public function unsetWebhook()
818
    {
819
        return $this->deleteWebhook();
820
    }
821
822
    /**
823
     * Delete any assigned webhook
824
     *
825
     * @return mixed
826
     * @throws \Longman\TelegramBot\Exception\TelegramException
827
     */
828
    public function deleteWebhook()
829
    {
830
        $result = Request::deleteWebhook();
831
832 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...
833
            throw new TelegramException(
834
                'Webhook was not deleted! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
835
            );
836
        }
837
838
        return $result;
839
    }
840
841
    /**
842
     * Replace function `ucwords` for UTF-8 characters in the class definition and commands
843
     *
844
     * @param string $str
845
     * @param string $encoding (default = 'UTF-8')
846
     *
847
     * @return string
848
     */
849 1
    protected function ucwordsUnicode($str, $encoding = 'UTF-8')
850
    {
851 1
        return mb_convert_case($str, MB_CASE_TITLE, $encoding);
852
    }
853
854
    /**
855
     * Replace function `ucfirst` for UTF-8 characters in the class definition and commands
856
     *
857
     * @param string $str
858
     * @param string $encoding (default = 'UTF-8')
859
     *
860
     * @return string
861
     */
862 1
    protected function ucfirstUnicode($str, $encoding = 'UTF-8')
863
    {
864
        return
865 1
            mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding)
866 1
            . mb_strtolower(mb_substr($str, 1, mb_strlen($str), $encoding), $encoding);
867
    }
868
869
    /**
870
     * Enable Botan.io integration
871
     *
872
     * @param  string $token
873
     * @param  array  $options
874
     *
875
     * @return \Longman\TelegramBot\Telegram
876
     * @throws \Longman\TelegramBot\Exception\TelegramException
877
     */
878
    public function enableBotan($token, array $options = [])
879
    {
880
        Botan::initializeBotan($token, $options);
881
        $this->botan_enabled = true;
882
883
        return $this;
884
    }
885
886
    /**
887
     * Enable requests limiter
888
     *
889
     * @param  array  $options
890
     *
891
     * @return \Longman\TelegramBot\Telegram
892
     */
893
    public function enableLimiter(array $options = [])
894
    {
895
        Request::setLimiter(true, $options);
896
897
        return $this;
898
    }
899
900
    /**
901
     * Run provided commands
902
     *
903
     * @param array $commands
904
     *
905
     * @throws TelegramException
906
     */
907
    public function runCommands($commands)
908
    {
909
        if (!is_array($commands) || empty($commands)) {
910
            throw new TelegramException('No command(s) provided!');
911
        }
912
913
        $this->run_commands = true;
914
        $this->botan_enabled = false;   // Force disable Botan.io integration, we don't want to track self-executed commands!
915
916
        $result = Request::getMe()->getResult();
917
918
        if (!$result->getId()) {
919
            throw new TelegramException('Received empty/invalid getMe result!');
920
        }
921
922
        $bot_id       = $result->getId();
923
        $bot_name     = $result->getFirstName();
924
        $bot_username = $result->getUsername();
925
926
        $this->enableAdmin($bot_id);    // Give bot access to admin commands
927
        $this->getCommandsList();       // Load full commands list
928
929
        foreach ($commands as $command) {
930
            $this->update = new Update(
931
                [
932
                    'update_id' => 0,
933
                    'message'   => [
934
                        'message_id' => 0,
935
                        'from'       => [
936
                            'id'         => $bot_id,
937
                            'first_name' => $bot_name,
938
                            'username'   => $bot_username,
939
                        ],
940
                        'date'       => time(),
941
                        'chat'       => [
942
                            'id'         => $bot_id,
943
                            'type'       => 'private',
944
                        ],
945
                        'text'       => $command,
946
                    ],
947
                ]
948
            );
949
950
            $this->executeCommand($this->update->getMessage()->getCommand());
0 ignored issues
show
Bug introduced by
It seems like $this->update->getMessage()->getCommand() targeting Longman\TelegramBot\Entities\Message::getCommand() can also be of type boolean; however, Longman\TelegramBot\Telegram::executeCommand() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
951
        }
952
    }
953
954
    /**
955
     * Is this session initiated by runCommands()
956
     *
957
     * @return bool
958
     */
959
    public function isRunCommands()
960
    {
961
        return $this->run_commands;
962
    }
963
}
964