Completed
Push — 772-prevent_system_command_cal... ( 411996...6e6ee9 )
by Armando
02:27
created

Telegram::addCommandsPath()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4.0312

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 7
cts 8
cp 0.875
rs 9.7998
c 0
b 0
f 0
cc 4
nc 4
nop 2
crap 4.0312
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" and "start" system commands to be called by user.
278
            // generic: as this is the fallback command anyway and to allow a custom fallback.
279
            //          DOWNSIDE is that no User or Admin '/generic' command is possible.
280
            // start:   to allow backwards compatibility.
281
            // @todo Implement proper command system...
282
            if ($auth === 'System' && $this->is_user_command && !in_array($command, ['start', 'generic'], true)) {
283
                continue;
284
            }
285
286
            $command_namespace = __NAMESPACE__ . '\\Commands\\' . $auth . 'Commands\\' . $this->ucfirstUnicode($command) . 'Command';
287
            if (class_exists($command_namespace)) {
288
                // For backwards compatibility, but throw deprecation error.
289
                // @todo Remove deprecation.
290
                if ($auth === 'System' && $command === 'start') {
291
                    trigger_error($command_namespace . ' is deprecated and will be removed and handled by ' . \Longman\TelegramBot\Commands\UserCommands\StartCommand::class . ' by default in a future release.', E_USER_DEPRECATED);
292
                }
293
294
                return new $command_namespace($this, $this->update);
295
            }
296
        }
297
298
        return null;
299
    }
300
301
    /**
302
     * Set custom input string for debug purposes
303
     *
304
     * @param string $input (json format)
305
     *
306
     * @return \Longman\TelegramBot\Telegram
307
     */
308
    public function setCustomInput($input)
309
    {
310
        $this->input = $input;
311
312
        return $this;
313
    }
314
315
    /**
316
     * Get custom input string for debug purposes
317
     *
318
     * @return string
319
     */
320
    public function getCustomInput()
321
    {
322
        return $this->input;
323
    }
324
325
    /**
326
     * Get the ServerResponse of the last Command execution
327
     *
328
     * @return \Longman\TelegramBot\Entities\ServerResponse
329
     */
330
    public function getLastCommandResponse()
331
    {
332
        return $this->last_command_response;
333
    }
334
335
    /**
336
     * Handle getUpdates method
337
     *
338
     * @param int|null $limit
339
     * @param int|null $timeout
340
     *
341
     * @return \Longman\TelegramBot\Entities\ServerResponse
342
     * @throws \Longman\TelegramBot\Exception\TelegramException
343
     */
344
    public function handleGetUpdates($limit = null, $timeout = null)
345
    {
346
        if (empty($this->bot_username)) {
347
            throw new TelegramException('Bot Username is not defined!');
348
        }
349
350
        if (!DB::isDbConnected() && !$this->getupdates_without_database) {
351
            return new ServerResponse(
352
                [
353
                    'ok'          => false,
354
                    'description' => 'getUpdates needs MySQL connection! (This can be overridden - see documentation)',
355
                ],
356
                $this->bot_username
357
            );
358
        }
359
360
        $offset = 0;
361
362
        //Take custom input into account.
363
        if ($custom_input = $this->getCustomInput()) {
364
            $response = new ServerResponse(json_decode($custom_input, true), $this->bot_username);
365
        } else {
366
            if (DB::isDbConnected()) {
367
                //Get last update id from the database
368
                $last_update = DB::selectTelegramUpdate(1);
369
                $last_update = reset($last_update);
370
371
                $this->last_update_id = isset($last_update['id']) ? $last_update['id'] : null;
372
            }
373
374
            if ($this->last_update_id !== null) {
375
                $offset = $this->last_update_id + 1;    //As explained in the telegram bot API documentation
376
            }
377
378
            $response = Request::getUpdates(
379
                [
380
                    'offset'  => $offset,
381
                    'limit'   => $limit,
382
                    'timeout' => $timeout,
383
                ]
384
            );
385
        }
386
387
        if ($response->isOk()) {
388
            $results = $response->getResult();
389
390
            //Process all updates
391
            /** @var Update $result */
392
            foreach ($results as $result) {
393
                $this->processUpdate($result);
394
            }
395
396
            if (!DB::isDbConnected() && !$custom_input && $this->last_update_id !== null && $offset === 0) {
397
                //Mark update(s) as read after handling
398
                Request::getUpdates(
399
                    [
400
                        'offset'  => $this->last_update_id + 1,
401
                        'limit'   => 1,
402
                        'timeout' => $timeout,
403
                    ]
404
                );
405
            }
406
        }
407
408
        return $response;
409
    }
410
411
    /**
412
     * Handle bot request from webhook
413
     *
414
     * @return bool
415
     *
416
     * @throws \Longman\TelegramBot\Exception\TelegramException
417
     */
418
    public function handle()
419
    {
420
        if (empty($this->bot_username)) {
421
            throw new TelegramException('Bot Username is not defined!');
422
        }
423
424
        $this->input = Request::getInput();
425
426
        if (empty($this->input)) {
427
            throw new TelegramException('Input is empty!');
428
        }
429
430
        $post = json_decode($this->input, true);
431
        if (empty($post)) {
432
            throw new TelegramException('Invalid JSON!');
433
        }
434
435
        if ($response = $this->processUpdate(new Update($post, $this->bot_username))) {
436
            return $response->isOk();
437
        }
438
439
        return false;
440
    }
441
442
    /**
443
     * Get the command name from the command type
444
     *
445
     * @param string $type
446
     *
447
     * @return string
448
     */
449
    protected function getCommandFromType($type)
450
    {
451
        return $this->ucfirstUnicode(str_replace('_', '', $type));
452
    }
453
454
    /**
455
     * Process bot Update request
456
     *
457
     * @param \Longman\TelegramBot\Entities\Update $update
458
     *
459
     * @return \Longman\TelegramBot\Entities\ServerResponse
460
     * @throws \Longman\TelegramBot\Exception\TelegramException
461
     */
462
    public function processUpdate(Update $update)
463
    {
464
        $this->update = $update;
465
        $this->last_update_id = $update->getUpdateId();
466
467
        //Load admin commands
468
        if ($this->isAdmin()) {
469
            $this->addCommandsPath(TB_BASE_COMMANDS_PATH . '/AdminCommands', false);
470
        }
471
472
        //Make sure we have an up-to-date command list
473
        //This is necessary to "require" all the necessary command files!
474
        $this->getCommandsList();
475
476
        //If all else fails, it's a generic message.
477
        $command = 'genericmessage';
478
479
        $this->is_user_command = false;
480
481
        $update_type = $this->update->getUpdateType();
482
        if ($update_type === 'message') {
483
            $message = $this->update->getMessage();
484
485
            $type = $message->getType();
486
            if ($type === 'command') {
487
                $this->is_user_command = true;
488
                $command               = $message->getCommand();
489
            } else {
490
                // Let's check if the message object has the type field we're looking for
491
                // and if a fitting command class is available.
492
                $command_tmp = $this->getCommandFromType($type);
493
                if ($this->getCommandObject($command_tmp) !== null) {
494
                    $command = $command_tmp;
495
                }
496
            }
497
        } else {
498
            $command = $this->getCommandFromType($update_type);
499
        }
500
501
        //Make sure we don't try to process update that was already processed
502
        $last_id = DB::selectTelegramUpdate(1, $this->update->getUpdateId());
503
        if ($last_id && count($last_id) === 1) {
504
            TelegramLog::debug('Duplicate update received, processing aborted!');
505
            return Request::emptyResponse();
506
        }
507
508
        DB::insertRequest($this->update);
509
510
        return $this->executeCommand($command);
511
    }
512
513
    /**
514
     * Execute /command
515
     *
516
     * @param string $command
517
     *
518
     * @return mixed
519
     * @throws \Longman\TelegramBot\Exception\TelegramException
520
     */
521
    public function executeCommand($command)
522
    {
523
        $command     = strtolower($command);
524
        $command_obj = $this->getCommandObject($command);
525
526
        if (!$command_obj || !$command_obj->isEnabled()) {
527
            //Failsafe in case the Generic command can't be found
528
            if ($command === 'generic') {
529
                throw new TelegramException('Generic command missing!');
530
            }
531
532
            //Handle a generic command or non existing one
533
            $this->last_command_response = $this->executeCommand('generic');
534
        } else {
535
            //execute() method is executed after preExecute()
536
            //This is to prevent executing a DB query without a valid connection
537
            $this->last_command_response = $command_obj->preExecute();
538
        }
539
540
        return $this->last_command_response;
541
    }
542
543
    /**
544
     * Sanitize Command
545
     *
546
     * @param string $command
547
     *
548
     * @return string
549
     */
550
    protected function sanitizeCommand($command)
551
    {
552
        return str_replace(' ', '', $this->ucwordsUnicode(str_replace('_', ' ', $command)));
553
    }
554
555
    /**
556
     * Enable a single Admin account
557
     *
558
     * @param integer $admin_id Single admin id
559
     *
560
     * @return \Longman\TelegramBot\Telegram
561
     */
562 1
    public function enableAdmin($admin_id)
563
    {
564 1
        if (!is_int($admin_id) || $admin_id <= 0) {
565 1
            TelegramLog::error('Invalid value "%s" for admin.', $admin_id);
566 1
        } elseif (!in_array($admin_id, $this->admins_list, true)) {
567 1
            $this->admins_list[] = $admin_id;
568
        }
569
570 1
        return $this;
571
    }
572
573
    /**
574
     * Enable a list of Admin Accounts
575
     *
576
     * @param array $admin_ids List of admin ids
577
     *
578
     * @return \Longman\TelegramBot\Telegram
579
     */
580 1
    public function enableAdmins(array $admin_ids)
581
    {
582 1
        foreach ($admin_ids as $admin_id) {
583 1
            $this->enableAdmin($admin_id);
584
        }
585
586 1
        return $this;
587
    }
588
589
    /**
590
     * Get list of admins
591
     *
592
     * @return array
593
     */
594 1
    public function getAdminList()
595
    {
596 1
        return $this->admins_list;
597
    }
598
599
    /**
600
     * Check if the passed user is an admin
601
     *
602
     * If no user id is passed, the current update is checked for a valid message sender.
603
     *
604
     * @param int|null $user_id
605
     *
606
     * @return bool
607
     */
608
    public function isAdmin($user_id = null)
609
    {
610
        if ($user_id === null && $this->update !== null) {
611
            //Try to figure out if the user is an admin
612
            $update_methods = [
613
                'getMessage',
614
                'getEditedMessage',
615
                'getChannelPost',
616
                'getEditedChannelPost',
617
                'getInlineQuery',
618
                'getChosenInlineResult',
619
                'getCallbackQuery',
620
            ];
621
            foreach ($update_methods as $update_method) {
622
                $object = call_user_func([$this->update, $update_method]);
623
                if ($object !== null && $from = $object->getFrom()) {
624
                    $user_id = $from->getId();
625
                    break;
626
                }
627
            }
628
        }
629
630
        return ($user_id === null) ? false : in_array($user_id, $this->admins_list, true);
631
    }
632
633
    /**
634
     * Check if user required the db connection
635
     *
636
     * @return bool
637
     */
638
    public function isDbEnabled()
639
    {
640
        if ($this->mysql_enabled) {
641
            return true;
642
        } else {
643
            return false;
644
        }
645
    }
646
647
    /**
648
     * Add a single custom commands path
649
     *
650
     * @param string $path   Custom commands path to add
651
     * @param bool   $before If the path should be prepended or appended to the list
652
     *
653
     * @return \Longman\TelegramBot\Telegram
654
     */
655 1
    public function addCommandsPath($path, $before = true)
656
    {
657 1
        if (!is_dir($path)) {
658 1
            TelegramLog::error('Commands path "%s" does not exist.', $path);
659 1
        } elseif (!in_array($path, $this->commands_paths, true)) {
660 1
            if ($before) {
661 1
                array_unshift($this->commands_paths, $path);
662
            } else {
663
                $this->commands_paths[] = $path;
664
            }
665
        }
666
667 1
        return $this;
668
    }
669
670
    /**
671
     * Add multiple custom commands paths
672
     *
673
     * @param array $paths  Custom commands paths to add
674
     * @param bool  $before If the paths should be prepended or appended to the list
675
     *
676
     * @return \Longman\TelegramBot\Telegram
677
     */
678 1
    public function addCommandsPaths(array $paths, $before = true)
679
    {
680 1
        foreach ($paths as $path) {
681 1
            $this->addCommandsPath($path, $before);
682
        }
683
684 1
        return $this;
685
    }
686
687
    /**
688
     * Return the list of commands paths
689
     *
690
     * @return array
691
     */
692 1
    public function getCommandsPaths()
693
    {
694 1
        return $this->commands_paths;
695
    }
696
697
    /**
698
     * Set custom upload path
699
     *
700
     * @param string $path Custom upload path
701
     *
702
     * @return \Longman\TelegramBot\Telegram
703
     */
704
    public function setUploadPath($path)
705
    {
706
        $this->upload_path = $path;
707
708
        return $this;
709
    }
710
711
    /**
712
     * Get custom upload path
713
     *
714
     * @return string
715
     */
716
    public function getUploadPath()
717
    {
718
        return $this->upload_path;
719
    }
720
721
    /**
722
     * Set custom download path
723
     *
724
     * @param string $path Custom download path
725
     *
726
     * @return \Longman\TelegramBot\Telegram
727
     */
728
    public function setDownloadPath($path)
729
    {
730
        $this->download_path = $path;
731
732
        return $this;
733
    }
734
735
    /**
736
     * Get custom download path
737
     *
738
     * @return string
739
     */
740
    public function getDownloadPath()
741
    {
742
        return $this->download_path;
743
    }
744
745
    /**
746
     * Set command config
747
     *
748
     * Provide further variables to a particular commands.
749
     * For example you can add the channel name at the command /sendtochannel
750
     * Or you can add the api key for external service.
751
     *
752
     * @param string $command
753
     * @param array  $config
754
     *
755
     * @return \Longman\TelegramBot\Telegram
756
     */
757 14
    public function setCommandConfig($command, array $config)
758
    {
759 14
        $this->commands_config[$command] = $config;
760
761 14
        return $this;
762
    }
763
764
    /**
765
     * Get command config
766
     *
767
     * @param string $command
768
     *
769
     * @return array
770
     */
771 14
    public function getCommandConfig($command)
772
    {
773 14
        return isset($this->commands_config[$command]) ? $this->commands_config[$command] : [];
774
    }
775
776
    /**
777
     * Get API key
778
     *
779
     * @return string
780
     */
781 1
    public function getApiKey()
782
    {
783 1
        return $this->api_key;
784
    }
785
786
    /**
787
     * Get Bot name
788
     *
789
     * @return string
790
     */
791 1
    public function getBotUsername()
792
    {
793 1
        return $this->bot_username;
794
    }
795
796
    /**
797
     * Get Bot Id
798
     *
799
     * @return string
800
     */
801
    public function getBotId()
802
    {
803
        return $this->bot_id;
804
    }
805
806
    /**
807
     * Get Version
808
     *
809
     * @return string
810
     */
811
    public function getVersion()
812
    {
813
        return $this->version;
814
    }
815
816
    /**
817
     * Set Webhook for bot
818
     *
819
     * @param string $url
820
     * @param array  $data Optional parameters.
821
     *
822
     * @return \Longman\TelegramBot\Entities\ServerResponse
823
     * @throws \Longman\TelegramBot\Exception\TelegramException
824
     */
825
    public function setWebhook($url, array $data = [])
826
    {
827
        if (empty($url)) {
828
            throw new TelegramException('Hook url is empty!');
829
        }
830
831
        $data        = array_intersect_key($data, array_flip([
832
            'certificate',
833
            'max_connections',
834
            'allowed_updates',
835
        ]));
836
        $data['url'] = $url;
837
838
        // If the certificate is passed as a path, encode and add the file to the data array.
839
        if (!empty($data['certificate']) && is_string($data['certificate'])) {
840
            $data['certificate'] = Request::encodeFile($data['certificate']);
841
        }
842
843
        $result = Request::setWebhook($data);
844
845 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...
846
            throw new TelegramException(
847
                'Webhook was not set! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
848
            );
849
        }
850
851
        return $result;
852
    }
853
854
    /**
855
     * Delete any assigned webhook
856
     *
857
     * @return mixed
858
     * @throws \Longman\TelegramBot\Exception\TelegramException
859
     */
860
    public function deleteWebhook()
861
    {
862
        $result = Request::deleteWebhook();
863
864 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...
865
            throw new TelegramException(
866
                'Webhook was not deleted! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
867
            );
868
        }
869
870
        return $result;
871
    }
872
873
    /**
874
     * Replace function `ucwords` for UTF-8 characters in the class definition and commands
875
     *
876
     * @param string $str
877
     * @param string $encoding (default = 'UTF-8')
878
     *
879
     * @return string
880
     */
881
    protected function ucwordsUnicode($str, $encoding = 'UTF-8')
882
    {
883
        return mb_convert_case($str, MB_CASE_TITLE, $encoding);
884
    }
885
886
    /**
887
     * Replace function `ucfirst` for UTF-8 characters in the class definition and commands
888
     *
889
     * @param string $str
890
     * @param string $encoding (default = 'UTF-8')
891
     *
892
     * @return string
893
     */
894
    protected function ucfirstUnicode($str, $encoding = 'UTF-8')
895
    {
896
        return mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding)
897
               . mb_strtolower(mb_substr($str, 1, mb_strlen($str), $encoding), $encoding);
898
    }
899
900
    /**
901
     * Enable Botan.io integration
902
     *
903
     * @deprecated Botan.io service is no longer working
904
     *
905
     * @param  string $token
906
     * @param  array  $options
907
     *
908
     * @return \Longman\TelegramBot\Telegram
909
     */
910
    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...
911
    {
912
        trigger_error('Longman\TelegramBot\Telegram::enableBotan is deprecated and will be removed in future release.', E_USER_DEPRECATED);
913
914
        return $this;
915
    }
916
917
    /**
918
     * Enable requests limiter
919
     *
920
     * @param  array $options
921
     *
922
     * @return \Longman\TelegramBot\Telegram
923
     */
924
    public function enableLimiter(array $options = [])
925
    {
926
        Request::setLimiter(true, $options);
927
928
        return $this;
929
    }
930
931
    /**
932
     * Run provided commands
933
     *
934
     * @param array $commands
935
     *
936
     * @throws TelegramException
937
     */
938
    public function runCommands($commands)
939
    {
940
        if (!is_array($commands) || empty($commands)) {
941
            throw new TelegramException('No command(s) provided!');
942
        }
943
944
        $this->run_commands  = true;
945
946
        $result = Request::getMe();
947
948
        if ($result->isOk()) {
949
            $result = $result->getResult();
950
951
            $bot_id       = $result->getId();
952
            $bot_name     = $result->getFirstName();
953
            $bot_username = $result->getUsername();
954
        } else {
955
            $bot_id       = $this->getBotId();
956
            $bot_name     = $this->getBotUsername();
957
            $bot_username = $this->getBotUsername();
958
        }
959
960
961
        $this->enableAdmin($bot_id);    // Give bot access to admin commands
962
        $this->getCommandsList();       // Load full commands list
963
964
        foreach ($commands as $command) {
965
            $this->update = new Update(
966
                [
967
                    'update_id' => 0,
968
                    'message'   => [
969
                        'message_id' => 0,
970
                        'from'       => [
971
                            'id'         => $bot_id,
972
                            'first_name' => $bot_name,
973
                            'username'   => $bot_username,
974
                        ],
975
                        'date'       => time(),
976
                        'chat'       => [
977
                            'id'   => $bot_id,
978
                            'type' => 'private',
979
                        ],
980
                        'text'       => $command,
981
                    ],
982
                ]
983
            );
984
985
            $this->executeCommand($this->update->getMessage()->getCommand());
986
        }
987
    }
988
989
    /**
990
     * Is this session initiated by runCommands()
991
     *
992
     * @return bool
993
     */
994
    public function isRunCommands()
995
    {
996
        return $this->run_commands;
997
    }
998
999
    /**
1000
     * Switch to enable running getUpdates without a database
1001
     *
1002
     * @param bool $enable
1003
     */
1004
    public function useGetUpdatesWithoutDatabase($enable = true)
1005
    {
1006
        $this->getupdates_without_database = $enable;
1007
    }
1008
1009
    /**
1010
     * Return last update id
1011
     *
1012
     * @return int
1013
     */
1014
    public function getLastUpdateId()
1015
    {
1016
        return $this->last_update_id;
1017
    }
1018
}
1019