Completed
Pull Request — develop (#457)
by
unknown
03:35 queued 54s
created

Telegram::setWebhook()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 8

Duplication

Lines 5
Ratio 31.25 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 5
loc 16
ccs 0
cts 8
cp 0
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 2
crap 12
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.41.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
     * Botan.io integration
128
     *
129
     * @var boolean
130
     */
131
    protected $botan_enabled = false;
132
133
    /**
134
     * Telegram constructor.
135
     *
136
     * @param string $api_key
137
     * @param string $bot_username
138
     *
139
     * @throws \Longman\TelegramBot\Exception\TelegramException
140
     */
141 41
    public function __construct($api_key, $bot_username)
142
    {
143 41
        if (empty($api_key)) {
144
            throw new TelegramException('API KEY not defined!');
145
        }
146
147 41
        if (empty($bot_username)) {
148
            throw new TelegramException('Bot Username not defined!');
149
        }
150
151 41
        $this->api_key  = $api_key;
152 41
        $this->bot_username = $bot_username;
153
154 41
        preg_match("/([0-9]*)\:.*/", $this->api_key, $matches);
155 41
        $this->bot_id = $matches[1];
156
157
        //Set default download and upload path
158
        $this->setDownloadPath(BASE_PATH . '/../Download');
159
        $this->setUploadPath(BASE_PATH . '/../Upload');
160
161
        //Add default system commands path
162
        $this->addCommandsPath(BASE_COMMANDS_PATH . '/SystemCommands');
163
164
        Request::initialize($this);
165
    }
166
167
    /**
168
     * Initialize Database connection
169
     *
170
     * @param array  $credential
171
     * @param string $table_prefix
172
     * @param string $encoding
173
     *
174
     * @return \Longman\TelegramBot\Telegram
175
     * @throws \Longman\TelegramBot\Exception\TelegramException
176
     */
177 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...
178
    {
179
        $this->pdo = DB::initialize($credential, $this, $table_prefix, $encoding);
180
        ConversationDB::initializeConversation();
181
        $this->mysql_enabled = true;
182
183
        return $this;
184
    }
185
186
    /**
187
     * Initialize Database external connection
188
     *
189
     * @param PDO    $external_pdo_connection PDO database object
190
     * @param string $table_prefix
191
     *
192
     * @return \Longman\TelegramBot\Telegram
193
     * @throws \Longman\TelegramBot\Exception\TelegramException
194
     */
195 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...
196
    {
197
        $this->pdo = DB::externalInitialize($external_pdo_connection, $this, $table_prefix);
198
        ConversationDB::initializeConversation();
199
        $this->mysql_enabled = true;
200
201
        return $this;
202
    }
203
204
    /**
205
     * Get commands list
206
     *
207
     * @return array $commands
208
     * @throws \Longman\TelegramBot\Exception\TelegramException
209
     */
210
    public function getCommandsList()
211
    {
212
        $commands = [];
213
214
        foreach ($this->commands_paths as $path) {
215
            try {
216
                //Get all "*Command.php" files
217
                $files = new RegexIterator(
218
                    new RecursiveIteratorIterator(
219
                        new RecursiveDirectoryIterator($path)
220
                    ),
221
                    '/^.+Command.php$/'
222
                );
223
224
                foreach ($files as $file) {
225
                    //Remove "Command.php" from filename
226
                    $command      = $this->sanitizeCommand(substr($file->getFilename(), 0, -11));
227
                    $command_name = strtolower($command);
228
229
                    if (array_key_exists($command_name, $commands)) {
230
                        continue;
231
                    }
232
233
                    require_once $file->getPathname();
234
235
                    $command_obj = $this->getCommandObject($command);
236
                    if ($command_obj instanceof Command) {
237
                        $commands[$command_name] = $command_obj;
238
                    }
239
                }
240
            } catch (Exception $e) {
241
                throw new TelegramException('Error getting commands from path: ' . $path);
242
            }
243
        }
244
245
        return $commands;
246
    }
247
248
    /**
249
     * Get an object instance of the passed command
250
     *
251
     * @param string $command
252
     *
253
     * @return \Longman\TelegramBot\Commands\Command|null
254
     */
255
    public function getCommandObject($command)
256
    {
257
        $which = ['System'];
258
        $this->isAdmin() && $which[] = 'Admin';
259
        $which[] = 'User';
260
261
        foreach ($which as $auth) {
262
            $command_namespace = __NAMESPACE__ . '\\Commands\\' . $auth . 'Commands\\' . $this->ucfirstUnicode($command) . 'Command';
263
            if (class_exists($command_namespace)) {
264
                return new $command_namespace($this, $this->update);
265
            }
266
        }
267
268
        return null;
269
    }
270
271
    /**
272
     * Set custom input string for debug purposes
273
     *
274
     * @param string $input (json format)
275
     *
276
     * @return \Longman\TelegramBot\Telegram
277
     */
278
    public function setCustomInput($input)
279
    {
280
        $this->input = $input;
281
282
        return $this;
283
    }
284
285
    /**
286
     * Get custom input string for debug purposes
287
     *
288
     * @return string
289
     */
290
    public function getCustomInput()
291
    {
292
        return $this->input;
293
    }
294
295
    /**
296
     * Get the ServerResponse of the last Command execution
297
     *
298
     * @return \Longman\TelegramBot\Entities\ServerResponse
299
     */
300
    public function getLastCommandResponse()
301
    {
302
        return $this->last_command_response;
303
    }
304
305
    /**
306
     * Handle getUpdates method
307
     *
308
     * @param int|null $limit
309
     * @param int|null $timeout
310
     *
311
     * @return \Longman\TelegramBot\Entities\ServerResponse
312
     * @throws \Longman\TelegramBot\Exception\TelegramException
313
     */
314
    public function handleGetUpdates($limit = null, $timeout = null)
315
    {
316
        if (!DB::isDbConnected()) {
317
            return new ServerResponse(
318
                [
319
                    'ok'          => false,
320
                    'description' => 'getUpdates needs MySQL connection!',
321
                ],
322
                $this->bot_username
323
            );
324
        }
325
326
        //DB Query
327
        $last_update = DB::selectTelegramUpdate(1);
328
        $last_update = reset($last_update);
329
330
        //As explained in the telegram bot api documentation
331
        $offset = isset($last_update['id']) ? $last_update['id'] + 1 : null;
332
333
        $response = Request::getUpdates(
334
            [
335
                'offset'  => $offset,
336
                'limit'   => $limit,
337
                'timeout' => $timeout,
338
            ]
339
        );
340
341
        if ($response->isOk()) {
342
            //Process all updates
343
            /** @var Update $result */
344
            foreach ((array) $response->getResult() as $result) {
345
                $this->processUpdate($result);
346
            }
347
        }
348
349
        return $response;
350
    }
351
352
    /**
353
     * Handle bot request from webhook
354
     *
355
     * @return bool
356
     *
357
     * @throws \Longman\TelegramBot\Exception\TelegramException
358
     */
359
    public function handle()
360
    {
361
        $this->input = Request::getInput();
362
363
        if (empty($this->input)) {
364
            throw new TelegramException('Input is empty!');
365
        }
366
367
        $post = json_decode($this->input, true);
368
        if (empty($post)) {
369
            throw new TelegramException('Invalid JSON!');
370
        }
371
372
        if ($response = $this->processUpdate(new Update($post, $this->bot_username))) {
373
            return $response->isOk();
374
        }
375
376
        return false;
377
    }
378
379
    /**
380
     * Get the command name from the command type
381
     *
382
     * @param string $type
383
     *
384
     * @return string
385
     */
386
    protected function getCommandFromType($type)
387
    {
388
        return $this->ucfirstUnicode(str_replace('_', '', $type));
389
    }
390
391
    /**
392
     * Process bot Update request
393
     *
394
     * @param \Longman\TelegramBot\Entities\Update $update
395
     *
396
     * @return \Longman\TelegramBot\Entities\ServerResponse
397
     * @throws \Longman\TelegramBot\Exception\TelegramException
398
     */
399
    public function processUpdate(Update $update)
400
    {
401
        $this->update = $update;
402
403
        //If all else fails, it's a generic message.
404
        $command = 'genericmessage';
405
406
        $update_type = $this->update->getUpdateType();
407
        if (in_array($update_type, ['edited_message', 'channel_post', 'edited_channel_post', 'inline_query', 'chosen_inline_result', 'callback_query'], true)) {
408
            $command = $this->getCommandFromType($update_type);
409
        } elseif ($update_type === 'message') {
410
            $message = $this->update->getMessage();
411
412
            //Load admin commands
413
            if ($this->isAdmin()) {
414
                $this->addCommandsPath(BASE_COMMANDS_PATH . '/AdminCommands', false);
415
            }
416
417
            $this->addCommandsPath(BASE_COMMANDS_PATH . '/UserCommands', false);
418
419
            $type = $message->getType();
420
            if ($type === 'command') {
421
                $command = $message->getCommand();
422
            } elseif (in_array($type, [
423
                'channel_chat_created',
424
                'delete_chat_photo',
425
                'group_chat_created',
426
                'left_chat_member',
427
                'migrate_from_chat_id',
428
                'migrate_to_chat_id',
429
                'new_chat_member',
430
                'new_chat_photo',
431
                'new_chat_title',
432
                'pinned_message',
433
                'supergroup_chat_created',
434
            ], true)
435
            ) {
436
                $command = $this->getCommandFromType($type);
437
            }
438
        }
439
440
        //Make sure we have an up-to-date command list
441
        //This is necessary to "require" all the necessary command files!
442
        $this->getCommandsList();
443
444
        DB::insertRequest($this->update);
445
446
        return $this->executeCommand($command);
0 ignored issues
show
Bug introduced by
It seems like $command defined by $message->getCommand() on line 421 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...
447
    }
448
449
    /**
450
     * Execute /command
451
     *
452
     * @param string $command
453
     *
454
     * @return mixed
455
     * @throws \Longman\TelegramBot\Exception\TelegramException
456
     */
457
    public function executeCommand($command)
458
    {
459
        $command_obj = $this->getCommandObject($command);
460
461
        if (!$command_obj || !$command_obj->isEnabled()) {
462
            //Failsafe in case the Generic command can't be found
463
            if ($command === 'Generic') {
464
                throw new TelegramException('Generic command missing!');
465
            }
466
467
            //Handle a generic command or non existing one
468
            $this->last_command_response = $this->executeCommand('Generic');
469
        } else {
470
            //Botan.io integration, make sure only the actual command user executed is reported
471
            if ($this->botan_enabled) {
472
                Botan::lock($command);
473
            }
474
475
            //execute() method is executed after preExecute()
476
            //This is to prevent executing a DB query without a valid connection
477
            $this->last_command_response = $command_obj->preExecute();
478
479
            //Botan.io integration, send report after executing the command
480
            if ($this->botan_enabled) {
481
                Botan::track($this->update, $command);
482
            }
483
        }
484
485
        return $this->last_command_response;
486
    }
487
488
    /**
489
     * Sanitize Command
490
     *
491
     * @param string $command
492
     *
493
     * @return string
494
     */
495
    protected function sanitizeCommand($command)
496
    {
497
        return str_replace(' ', '', $this->ucwordsUnicode(str_replace('_', ' ', $command)));
498
    }
499
500
    /**
501
     * Enable a single Admin account
502
     *
503
     * @param integer $admin_id Single admin id
504
     *
505
     * @return \Longman\TelegramBot\Telegram
506
     */
507
    public function enableAdmin($admin_id)
508
    {
509
        if (is_int($admin_id) && $admin_id > 0 && !in_array($admin_id, $this->admins_list, true)) {
510
            $this->admins_list[] = $admin_id;
511
        } else {
512
            TelegramLog::error('Invalid value "%s" for admin.', $admin_id);
513
        }
514
515
        return $this;
516
    }
517
518
    /**
519
     * Enable a list of Admin Accounts
520
     *
521
     * @param array $admin_ids List of admin ids
522
     *
523
     * @return \Longman\TelegramBot\Telegram
524
     */
525
    public function enableAdmins(array $admin_ids)
526
    {
527
        foreach ($admin_ids as $admin_id) {
528
            $this->enableAdmin($admin_id);
529
        }
530
531
        return $this;
532
    }
533
534
    /**
535
     * Get list of admins
536
     *
537
     * @return array
538
     */
539
    public function getAdminList()
540
    {
541
        return $this->admins_list;
542
    }
543
544
    /**
545
     * Check if the passed user is an admin
546
     *
547
     * If no user id is passed, the current update is checked for a valid message sender.
548
     *
549
     * @param int|null $user_id
550
     *
551
     * @return bool
552
     */
553
    public function isAdmin($user_id = null)
554
    {
555
        if ($user_id === null && $this->update !== null) {
556
            //Try to figure out if the user is an admin
557
            $update_methods = [
558
                'getMessage',
559
                'getEditedMessage',
560
                'getChannelPost',
561
                'getEditedChannelPost',
562
                'getInlineQuery',
563
                'getChosenInlineResult',
564
                'getCallbackQuery',
565
            ];
566
            foreach ($update_methods as $update_method) {
567
                $object = call_user_func([$this->update, $update_method]);
568
                if ($object !== null && $from = $object->getFrom()) {
569
                    $user_id = $from->getId();
570
                    break;
571
                }
572
            }
573
        }
574
575
        return ($user_id === null) ? false : in_array($user_id, $this->admins_list, true);
576
    }
577
578
    /**
579
     * Check if user required the db connection
580
     *
581
     * @return bool
582
     */
583
    public function isDbEnabled()
584
    {
585
        if ($this->mysql_enabled) {
586
            return true;
587
        } else {
588
            return false;
589
        }
590
    }
591
592
    /**
593
     * Add a single custom commands path
594
     *
595
     * @param string $path   Custom commands path to add
596
     * @param bool   $before If the path should be prepended or appended to the list
597
     *
598
     * @return \Longman\TelegramBot\Telegram
599
     */
600
    public function addCommandsPath($path, $before = true)
601
    {
602
        if (!is_dir($path)) {
603
            TelegramLog::error('Commands path "%s" does not exist.', $path);
604
        } elseif (!in_array($path, $this->commands_paths, true)) {
605
            if ($before) {
606
                array_unshift($this->commands_paths, $path);
607
            } else {
608
                $this->commands_paths[] = $path;
609
            }
610
        }
611
612
        return $this;
613
    }
614
615
    /**
616
     * Add multiple custom commands paths
617
     *
618
     * @param array $paths  Custom commands paths to add
619
     * @param bool  $before If the paths should be prepended or appended to the list
620
     *
621
     * @return \Longman\TelegramBot\Telegram
622
     */
623
    public function addCommandsPaths(array $paths, $before = true)
624
    {
625
        foreach ($paths as $path) {
626
            $this->addCommandsPath($path, $before);
627
        }
628
629
        return $this;
630
    }
631
632
    /**
633
     * Return the list of commands paths
634
     *
635
     * @return array
636
     */
637
    public function getCommandsPaths()
638
    {
639
        return $this->commands_paths;
640
    }
641
642
    /**
643
     * Set custom upload path
644
     *
645
     * @param string $path Custom upload path
646
     *
647
     * @return \Longman\TelegramBot\Telegram
648
     */
649
    public function setUploadPath($path)
650
    {
651
        $this->upload_path = $path;
652
653
        return $this;
654
    }
655
656
    /**
657
     * Get custom upload path
658
     *
659
     * @return string
660
     */
661
    public function getUploadPath()
662
    {
663
        return $this->upload_path;
664
    }
665
666
    /**
667
     * Set custom download path
668
     *
669
     * @param string $path Custom download path
670
     *
671
     * @return \Longman\TelegramBot\Telegram
672
     */
673
    public function setDownloadPath($path)
674
    {
675
        $this->download_path = $path;
676
677
        return $this;
678
    }
679
680
    /**
681
     * Get custom download path
682
     *
683
     * @return string
684
     */
685
    public function getDownloadPath()
686
    {
687
        return $this->download_path;
688
    }
689
690
    /**
691
     * Set command config
692
     *
693
     * Provide further variables to a particular commands.
694
     * For example you can add the channel name at the command /sendtochannel
695
     * Or you can add the api key for external service.
696
     *
697
     * @param string $command
698
     * @param array  $config
699
     *
700
     * @return \Longman\TelegramBot\Telegram
701
     */
702
    public function setCommandConfig($command, array $config)
703
    {
704
        $this->commands_config[$command] = $config;
705
706
        return $this;
707
    }
708
709
    /**
710
     * Get command config
711
     *
712
     * @param string $command
713
     *
714
     * @return array
715
     */
716
    public function getCommandConfig($command)
717
    {
718
        return isset($this->commands_config[$command]) ? $this->commands_config[$command] : [];
719
    }
720
721
    /**
722
     * Get API key
723
     *
724
     * @return string
725
     */
726
    public function getApiKey()
727
    {
728
        return $this->api_key;
729
    }
730
731
    /**
732
     * Get Bot name
733
     *
734
     * @return string
735
     */
736
    public function getBotUsername()
737
    {
738
        return $this->bot_username;
739
    }
740
741
    /**
742
     * Get Bot name
743
     *  @todo: Left for backwards compatibility, remove in the future
744
     *
745
     * @return string
746
     */
747
    public function getBotName()
748
    {
749
        TelegramLog::debug('Usage of deprecated method getBotName() detected, please use getBotUsername() instead!');
750
        return $this->getBotUsername();
751
    }
752
753
    /**
754
     * Get Bot Id
755
     *
756
     * @return string
757
     */
758
    public function getBotId()
759
    {
760
        return $this->bot_id;
761
    }
762
763
    /**
764
     * Get Version
765
     *
766
     * @return string
767
     */
768
    public function getVersion()
769
    {
770
        return $this->version;
771
    }
772
773
    /**
774
     * Set Webhook for bot
775
     *
776
     * @param string $url
777
     * @param array  $data Optional parameters.
778
     *
779
     * @return \Longman\TelegramBot\Entities\ServerResponse
780
     * @throws \Longman\TelegramBot\Exception\TelegramException
781
     */
782
    public function setWebhook($url, array $data = [])
783
    {
784
        if (empty($url)) {
785
            throw new TelegramException('Hook url is empty!');
786
        }
787
788
        $result = Request::setWebhook($url, $data);
789
790 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...
791
            throw new TelegramException(
792
                'Webhook was not set! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
793
            );
794
        }
795
796
        return $result;
797
    }
798
799
    /**
800
     * Deprecated alias for deleteWebhook
801
     *
802
     * This is kept for backwards compatibility!
803
     *
804
     * @return mixed
805
     * @throws \Longman\TelegramBot\Exception\TelegramException
806
     */
807
    public function unsetWebhook()
808
    {
809
        return $this->deleteWebhook();
810
    }
811
812
    /**
813
     * Delete any assigned webhook
814
     *
815
     * @return mixed
816
     * @throws \Longman\TelegramBot\Exception\TelegramException
817
     */
818
    public function deleteWebhook()
819
    {
820
        $result = Request::deleteWebhook();
821
822 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...
823
            throw new TelegramException(
824
                'Webhook was not deleted! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
825
            );
826
        }
827
828
        return $result;
829
    }
830
831
    /**
832
     * Replace function `ucwords` for UTF-8 characters in the class definition and commands
833
     *
834
     * @param string $str
835
     * @param string $encoding (default = 'UTF-8')
836
     *
837
     * @return string
838
     */
839
    protected function ucwordsUnicode($str, $encoding = 'UTF-8')
840
    {
841
        return mb_convert_case($str, MB_CASE_TITLE, $encoding);
842
    }
843
844
    /**
845
     * Replace function `ucfirst` for UTF-8 characters in the class definition and commands
846
     *
847
     * @param string $str
848
     * @param string $encoding (default = 'UTF-8')
849
     *
850
     * @return string
851
     */
852
    protected function ucfirstUnicode($str, $encoding = 'UTF-8')
853
    {
854
        return
855
            mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding)
856
            . mb_strtolower(mb_substr($str, 1, mb_strlen($str), $encoding), $encoding);
857
    }
858
859
    /**
860
     * Enable Botan.io integration
861
     *
862
     * @param  string $token
863
     * @param  array $options
864
     *
865
     * @return \Longman\TelegramBot\Telegram
866
     * @throws \Longman\TelegramBot\Exception\TelegramException
867
     */
868
    public function enableBotan($token, array $options = [])
869
    {
870
        Botan::initializeBotan($token, $options);
871
        $this->botan_enabled = true;
872
873
        return $this;
874
    }
875
876
    /**
877
     * Enable requests limiter
878
     */
879
    public function enableLimiter()
880
    {
881
        Request::setLimiter(true);
882
883
        return $this;
884
    }
885
    
886
    /**
887
     * Run provided commands
888
     *
889
     * @param array $commands
890
     *
891
     * @throws TelegramException
892
     */
893
    public function runCommands($commands)
894
    {
895
        if (!is_array($commands) || empty($commands)) {
896
            throw new TelegramException('No command(s) provided!');
897
        }
898
899
        $this->botan_enabled = false;   // Force disable Botan.io integration, we don't want to track self-executed commands!
900
901
        $result = Request::getMe()->getResult();
902
903
        if (!$result->getId()) {
904
            throw new TelegramException('Received empty/invalid getMe result!');
905
        }
906
907
        $bot_id       = $result->getId();
908
        $bot_name     = $result->getFirstName();
909
        $bot_username = $result->getUsername();
910
911
        $this->enableAdmin($bot_id);    // Give bot access to admin commands
912
        $this->getCommandsList();       // Load full commands list
913
914
        foreach ($commands as $command) {
915
            $this->update = new Update(
916
                [
917
                    'update_id' => 0,
918
                    'message'   => [
919
                        'message_id' => 0,
920
                        'from'       => [
921
                            'id'         => $bot_id,
922
                            'first_name' => $bot_name,
923
                            'username'   => $bot_username
924
                        ],
925
                        'date'       => time(),
926
                        'chat'       => [
927
                            'id'   => $bot_id,
928
                            'type' => 'private',
929
                        ],
930
                        'text'       => $command
931
                    ]
932
                ]
933
            );
934
935
            $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...
936
        }
937
    }
938
}
939