Completed
Push — 772-prevent_system_command_cal... ( 995cdc...9c7b1d )
by Armando
02:28
created

Telegram::isRunCommands()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

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

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
905
    {
906
        trigger_error('Longman\TelegramBot\Telegram::enableBotan is deprecated and will be removed in future release.', E_USER_DEPRECATED);
907
908
        return $this;
909
    }
910
911
    /**
912
     * Enable requests limiter
913
     *
914
     * @param  array $options
915
     *
916
     * @return \Longman\TelegramBot\Telegram
917
     */
918
    public function enableLimiter(array $options = [])
919
    {
920
        Request::setLimiter(true, $options);
921
922
        return $this;
923
    }
924
925
    /**
926
     * Run provided commands
927
     *
928
     * @param array $commands
929
     *
930
     * @throws TelegramException
931
     */
932
    public function runCommands($commands)
933
    {
934
        if (!is_array($commands) || empty($commands)) {
935
            throw new TelegramException('No command(s) provided!');
936
        }
937
938
        $this->run_commands  = true;
939
940
        $result = Request::getMe();
941
942
        if ($result->isOk()) {
943
            $result = $result->getResult();
944
945
            $bot_id       = $result->getId();
946
            $bot_name     = $result->getFirstName();
947
            $bot_username = $result->getUsername();
948
        } else {
949
            $bot_id       = $this->getBotId();
950
            $bot_name     = $this->getBotUsername();
951
            $bot_username = $this->getBotUsername();
952
        }
953
954
955
        $this->enableAdmin($bot_id);    // Give bot access to admin commands
956
        $this->getCommandsList();       // Load full commands list
957
958
        foreach ($commands as $command) {
959
            $this->update = new Update(
960
                [
961
                    'update_id' => 0,
962
                    'message'   => [
963
                        'message_id' => 0,
964
                        'from'       => [
965
                            'id'         => $bot_id,
966
                            'first_name' => $bot_name,
967
                            'username'   => $bot_username,
968
                        ],
969
                        'date'       => time(),
970
                        'chat'       => [
971
                            'id'   => $bot_id,
972
                            'type' => 'private',
973
                        ],
974
                        'text'       => $command,
975
                    ],
976
                ]
977
            );
978
979
            $this->executeCommand($this->update->getMessage()->getCommand());
980
        }
981
    }
982
983
    /**
984
     * Is this session initiated by runCommands()
985
     *
986
     * @return bool
987
     */
988
    public function isRunCommands()
989
    {
990
        return $this->run_commands;
991
    }
992
993
    /**
994
     * Switch to enable running getUpdates without a database
995
     *
996
     * @param bool $enable
997
     */
998
    public function useGetUpdatesWithoutDatabase($enable = true)
999
    {
1000
        $this->getupdates_without_database = $enable;
1001
    }
1002
1003
    /**
1004
     * Return last update id
1005
     *
1006
     * @return int
1007
     */
1008
    public function getLastUpdateId()
1009
    {
1010
        return $this->last_update_id;
1011
    }
1012
}
1013