Completed
Push — feature/refactor-app-design ( a2f6ee...c863f7 )
by Avtandil
02:30
created

Telegram::enableLimiter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
ccs 0
cts 3
cp 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
crap 2
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 13 and the first side effect is on line 13.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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 Illuminate\Container\Container;
18
use Longman\TelegramBot\Commands\Command;
19
use Longman\TelegramBot\Console\Kernel as ConsoleKernel;
20
use Longman\TelegramBot\Entities\Update;
21
use Longman\TelegramBot\Exception\TelegramException;
22
use Longman\TelegramBot\Http\Client;
23
use Longman\TelegramBot\Http\Kernel;
24
use Longman\TelegramBot\Http\Request;
25
use Longman\TelegramBot\Http\Response;
26
use PDO;
27
use RecursiveDirectoryIterator;
28
use RecursiveIteratorIterator;
29
use RegexIterator;
30
31
class Telegram extends Container
32
{
33
    /**
34
     * Version
35
     *
36
     * @var string
37
     */
38
    const VERSION = '0.53.0';
39
40
    /**
41
     * Telegram API key
42
     *
43
     * @var string
44
     */
45
    protected $api_key = '';
46
47
    /**
48
     * Telegram Bot username
49
     *
50
     * @var string
51
     */
52
    protected $bot_username = '';
53
54
    /**
55
     * Telegram Bot id
56
     *
57
     * @var string
58
     */
59
    protected $bot_id = '';
60
61
    /**
62
     * Container
63
     *
64
     * @var \Illuminate\Contracts\Container\Container
65
     */
66
    protected $container;
67
68
    /**
69
     * Raw request data (json) for webhook methods
70
     *
71
     * @var string
72
     */
73
    protected $input;
74
75
    /**
76
     * Custom commands paths
77
     *
78
     * @var array
79
     */
80
    protected $commands_paths = [];
81
82
    /**
83
     * Current Update object
84
     *
85
     * @var \Longman\TelegramBot\Entities\Update
86
     */
87
    protected $update;
88
89
    /**
90
     * Upload path
91
     *
92
     * @var string
93
     */
94
    protected $upload_path;
95
96
    /**
97
     * Download path
98
     *
99
     * @var string
100
     */
101
    protected $download_path;
102
103
    /**
104
     * MySQL integration
105
     *
106
     * @var boolean
107
     */
108
    protected $mysql_enabled = false;
109
110
    /**
111
     * PDO object
112
     *
113
     * @var \PDO
114
     */
115
    protected $pdo;
116
117
    /**
118
     * Commands config
119
     *
120
     * @var array
121
     */
122
    protected $commands_config = [];
123
124
    /**
125
     * Admins list
126
     *
127
     * @var array
128
     */
129
    protected $admins_list = [];
130
131
    /**
132
     * ServerResponse of the last Command execution
133
     *
134
     * @var \Longman\TelegramBot\Http\Response
135
     */
136
    protected $last_command_response;
137
138
    /**
139
     * Botan.io integration
140
     *
141
     * @var boolean
142
     */
143
    protected $botan_enabled = false;
144
145
    /**
146
     * Check if runCommands() is running in this session
147
     *
148
     * @var boolean
149
     */
150
    protected $run_commands = false;
151
152
    /**
153
     * Is running getUpdates without DB enabled
154
     *
155
     * @var bool
156
     */
157
    public $getupdates_without_database = false;
158
159
    /**
160
     * Last update ID
161
     * Only used when running getUpdates without a database
162
     *
163
     * @var integer
164
     */
165
    public $last_update_id = null;
166
167
    /**
168
     * Telegram constructor.
169
     *
170
     * @param string $api_key
171
     * @param string $bot_username
172
     *
173
     * @throws \Longman\TelegramBot\Exception\TelegramException
174
     */
175 32
    public function __construct($api_key, $bot_username = '')
176
    {
177 32
        if (empty($api_key)) {
178 1
            throw new TelegramException('API KEY not defined!');
179
        }
180 32
        preg_match('/(\d+)\:[\w\-]+/', $api_key, $matches);
181 32
        if (! isset($matches[1])) {
182 1
            throw new TelegramException('Invalid API KEY defined!');
183
        }
184 32
        $this->bot_id = $matches[1];
185 32
        $this->api_key = $api_key;
186
187 32
        if (! empty($bot_username)) {
188 32
            $this->bot_username = $bot_username;
189
        }
190
191 32
        $this->registerBaseBindings();
192
193
        //Add default system commands path
194 32
        $this->addCommandsPath(TB_BASE_COMMANDS_PATH . '/SystemCommands');
195
196 32
        Client::initialize($this);
197 32
    }
198
199
    /**
200
     * Register the basic bindings into the container.
201
     *
202
     * @return void
203
     */
204 32
    protected function registerBaseBindings()
205
    {
206 32
        static::setInstance($this);
207
208 32
        $this->instance('app', $this);
209
210 32
        $this->instance(Telegram::class, $this);
211 32
    }
212
213
    /**
214
     * Initialize Database connection
215
     *
216
     * @param array $credential
217
     * @param string $table_prefix
218
     * @param string $encoding
219
     *
220
     * @return \Longman\TelegramBot\Telegram
221
     * @throws \Longman\TelegramBot\Exception\TelegramException
222
     */
223 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...
224
    {
225 9
        $this->pdo = DB::initialize($credential, $this, $table_prefix, $encoding);
226 9
        ConversationDB::initializeConversation();
227 9
        $this->mysql_enabled = true;
228
229 9
        return $this;
230
    }
231
232
    /**
233
     * Initialize Database external connection
234
     *
235
     * @param PDO $external_pdo_connection PDO database object
236
     * @param string $table_prefix
237
     *
238
     * @return \Longman\TelegramBot\Telegram
239
     * @throws \Longman\TelegramBot\Exception\TelegramException
240
     */
241 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...
242
    {
243
        $this->pdo = DB::externalInitialize($external_pdo_connection, $this, $table_prefix);
244
        ConversationDB::initializeConversation();
245
        $this->mysql_enabled = true;
246
247
        return $this;
248
    }
249
250
    /**
251
     * Get commands list
252
     *
253
     * @return array $commands
254
     * @throws \Longman\TelegramBot\Exception\TelegramException
255
     */
256 2
    public function getCommandsList()
257
    {
258 2
        $commands = [];
259
260 2
        foreach ($this->commands_paths as $path) {
261
            try {
262
                //Get all "*Command.php" files
263 2
                $files = new RegexIterator(
264 2
                    new RecursiveIteratorIterator(
265 2
                        new RecursiveDirectoryIterator($path)
266
                    ),
267 2
                    '/^.+Command.php$/'
268
                );
269
270 2
                foreach ($files as $file) {
271
                    //Remove "Command.php" from filename
272 2
                    $command = $this->sanitizeCommand(substr($file->getFilename(), 0, -11));
273 2
                    $command_name = strtolower($command);
274
275 2
                    if (array_key_exists($command_name, $commands)) {
276
                        continue;
277
                    }
278
279 2
                    require_once $file->getPathname();
280
281 2
                    $command_obj = $this->getCommandObject($command);
282 2
                    if ($command_obj instanceof Command) {
283 2
                        $commands[$command_name] = $command_obj;
284
                    }
285
                }
286
            } catch (Exception $e) {
287 2
                throw new TelegramException('Error getting commands from path: ' . $path);
288
            }
289
        }
290
291 2
        return $commands;
292
    }
293
294
    /**
295
     * Get an object instance of the passed command
296
     *
297
     * @param string $command
298
     *
299
     * @return \Longman\TelegramBot\Commands\Command|null
300
     */
301 2
    public function getCommandObject($command)
302
    {
303 2
        $which = ['System'];
304 2
        $this->isAdmin() && $which[] = 'Admin';
305 2
        $which[] = 'User';
306
307 2
        foreach ($which as $auth) {
308 2
            $command_namespace = __NAMESPACE__ . '\\Commands\\' . $auth . 'Commands\\' . $this->ucfirstUnicode($command) . 'Command';
309 2
            if (class_exists($command_namespace)) {
310 2
                return new $command_namespace($this, $this->update);
311
            }
312
        }
313
314 1
        return null;
315
    }
316
317
    /**
318
     * Set custom input string for debug purposes
319
     *
320
     * @param string $input (json format)
321
     *
322
     * @return \Longman\TelegramBot\Telegram
323
     */
324
    public function setCustomInput($input)
325
    {
326
        $this->input = $input;
327
328
        return $this;
329
    }
330
331
    /**
332
     * Get custom input string for debug purposes
333
     *
334
     * @return string
335
     */
336
    public function getCustomInput()
337
    {
338
        return $this->input;
339
    }
340
341
    /**
342
     * Get the ServerResponse of the last Command execution
343
     *
344
     * @return \Longman\TelegramBot\Http\Response
345
     */
346
    public function getLastCommandResponse()
347
    {
348
        return $this->last_command_response;
349
    }
350
351
    /**
352
     * Handle getUpdates method
353
     *
354
     * @param int|null $limit
355
     * @param int|null $timeout
356
     *
357
     * @return \Longman\TelegramBot\Http\Response
358
     * @throws \Longman\TelegramBot\Exception\TelegramException
359
     */
360
    public function handleGetUpdates($limit = null, $timeout = null)
361
    {
362
        if (empty($this->bot_username)) {
363
            throw new TelegramException('Bot Username is not defined!');
364
        }
365
366
        /** @var \Longman\TelegramBot\Console\Kernel $kernel */
367
        $kernel = $this->make(ConsoleKernel::class);
368
369
        $response = $kernel->handle(Request::capture(), $limit, $timeout);
0 ignored issues
show
Bug introduced by
It seems like $limit defined by parameter $limit on line 360 can also be of type integer; however, Longman\TelegramBot\Console\Kernel::handle() does only seem to accept null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and 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...
Bug introduced by
It seems like $timeout defined by parameter $timeout on line 360 can also be of type integer; however, Longman\TelegramBot\Console\Kernel::handle() does only seem to accept null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and 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...
370
371
        return $response;
372
    }
373
374
    /**
375
     * Handle bot request from webhook
376
     *
377
     * @return bool
378
     *
379
     * @throws \Longman\TelegramBot\Exception\TelegramException
380
     */
381 1
    public function handle()
382
    {
383 1
        if (empty($this->bot_username)) {
384
            throw new TelegramException('Bot Username is not defined!');
385
        }
386
387
        /** @var \Longman\TelegramBot\Http\Kernel $kernel */
388 1
        $kernel = $this->make(Kernel::class);
389
390 1
        $response = $kernel->handle(Request::capture());
391
392 1
        return $response;
393
    }
394
395
    /**
396
     * Get the command name from the command type
397
     *
398
     * @param string $type
399
     *
400
     * @return string
401
     */
402 1
    protected function getCommandFromType($type)
403
    {
404 1
        return $this->ucfirstUnicode(str_replace('_', '', $type));
405
    }
406
407
    /**
408
     * Process bot Update request
409
     *
410
     * @param \Longman\TelegramBot\Entities\Update $update
411
     *
412
     * @return \Longman\TelegramBot\Http\Response
413
     * @throws \Longman\TelegramBot\Exception\TelegramException
414
     */
415 1
    public function processUpdate(Update $update)
416
    {
417 1
        $this->update = $update;
418 1
        $this->last_update_id = $update->getUpdateId();
419
420
        // If all else fails, it's a generic message.
421 1
        $command = 'genericmessage';
422
423 1
        $update_type = $this->update->getUpdateType();
424 1
        if ($update_type === 'message') {
425
            $message = $this->update->getMessage();
426
427
            // Load admin commands
428
            if ($this->isAdmin()) {
429
                $this->addCommandsPath(TB_BASE_COMMANDS_PATH . '/AdminCommands', false);
430
            }
431
432
            $type = $message->getType();
433
            if ($type === 'command') {
434
                $command = $message->getCommand();
435
            } else if (in_array($type, [
436
                'new_chat_members',
437
                'left_chat_member',
438
                'new_chat_title',
439
                'new_chat_photo',
440
                'delete_chat_photo',
441
                'group_chat_created',
442
                'supergroup_chat_created',
443
                'channel_chat_created',
444
                'migrate_to_chat_id',
445
                'migrate_from_chat_id',
446
                'pinned_message',
447
                'invoice',
448
                'successful_payment',
449
            ], true)
450
            ) {
451
                $command = $this->getCommandFromType($type);
452
            }
453
        } else {
454 1
            $command = $this->getCommandFromType($update_type);
455
        }
456
457
        // Make sure we have an up-to-date command list
458
        // This is necessary to "require" all the necessary command files!
459 1
        $this->getCommandsList();
460
461
        // Make sure we don't try to process update that was already processed
462 1
        $last_id = DB::selectTelegramUpdate(1, $this->update->getUpdateId());
463 1
        if ($last_id && count($last_id) === 1) {
464
            TelegramLog::debug('Duplicate update received, processing aborted!');
465
466
            return new Response(['ok' => true, 'result' => true]);
467
        }
468
469 1
        DB::insertRequest($this->update);
470
471 1
        return $this->executeCommand($command);
472
    }
473
474
    /**
475
     * Execute /command
476
     *
477
     * @param string $command
478
     *
479
     * @return mixed
480
     * @throws \Longman\TelegramBot\Exception\TelegramException
481
     */
482 1
    public function executeCommand($command)
483
    {
484 1
        $command = strtolower($command);
485 1
        $command_obj = $this->getCommandObject($command);
486
487 1
        if (! $command_obj || ! $command_obj->isEnabled()) {
488
            // Failsafe in case the Generic command can't be found
489 1
            if ($command === 'generic') {
490
                throw new TelegramException('Generic command missing!');
491
            }
492
493
            // Handle a generic command or non existing one
494 1
            $this->last_command_response = $this->executeCommand('generic');
495
        } else {
496
            // Botan.io integration, make sure only the actual command user executed is reported
497 1
            if ($this->botan_enabled) {
498
                Botan::lock($command);
499
            }
500
501
            // execute() method is executed after preExecute()
502
            // This is to prevent executing a DB query without a valid connection
503 1
            $this->last_command_response = $command_obj->preExecute();
504
505
            // Botan.io integration, send report after executing the command
506 1
            if ($this->botan_enabled) {
507
                Botan::track($this->update, $command);
508
            }
509
        }
510
511 1
        return $this->last_command_response;
512
    }
513
514
    /**
515
     * Sanitize Command
516
     *
517
     * @param string $command
518
     *
519
     * @return string
520
     */
521 2
    protected function sanitizeCommand($command)
522
    {
523 2
        return str_replace(' ', '', $this->ucwordsUnicode(str_replace('_', ' ', $command)));
524
    }
525
526
    /**
527
     * Enable a single Admin account
528
     *
529
     * @param integer $admin_id Single admin id
530
     *
531
     * @return \Longman\TelegramBot\Telegram
532
     */
533 1
    public function enableAdmin($admin_id)
534
    {
535 1
        if (! is_int($admin_id) || $admin_id <= 0) {
536 1
            TelegramLog::error('Invalid value "%s" for admin.', $admin_id);
537 1
        } else if (! in_array($admin_id, $this->admins_list, true)) {
538 1
            $this->admins_list[] = $admin_id;
539
        }
540
541 1
        return $this;
542
    }
543
544
    /**
545
     * Enable a list of Admin Accounts
546
     *
547
     * @param array $admin_ids List of admin ids
548
     *
549
     * @return \Longman\TelegramBot\Telegram
550
     */
551 1
    public function enableAdmins(array $admin_ids)
552
    {
553 1
        foreach ($admin_ids as $admin_id) {
554 1
            $this->enableAdmin($admin_id);
555
        }
556
557 1
        return $this;
558
    }
559
560
    /**
561
     * Get list of admins
562
     *
563
     * @return array
564
     */
565 1
    public function getAdminList()
566
    {
567 1
        return $this->admins_list;
568
    }
569
570
    /**
571
     * Check if the passed user is an admin
572
     *
573
     * If no user id is passed, the current update is checked for a valid message sender.
574
     *
575
     * @param int|null $user_id
576
     *
577
     * @return bool
578
     */
579 2
    public function isAdmin($user_id = null)
580
    {
581 2
        if ($user_id === null && $this->update !== null) {
582
            //Try to figure out if the user is an admin
583
            $update_methods = [
584 1
                'getMessage',
585
                'getEditedMessage',
586
                'getChannelPost',
587
                'getEditedChannelPost',
588
                'getInlineQuery',
589
                'getChosenInlineResult',
590
                'getCallbackQuery',
591
            ];
592 1
            foreach ($update_methods as $update_method) {
593 1
                $object = call_user_func([$this->update, $update_method]);
594 1
                if ($object !== null && $from = $object->getFrom()) {
595
                    $user_id = $from->getId();
596 1
                    break;
597
                }
598
            }
599
        }
600
601 2
        return ($user_id === null) ? false : in_array($user_id, $this->admins_list, true);
602
    }
603
604
    /**
605
     * Check if user required the db connection
606
     *
607
     * @return bool
608
     */
609
    public function isDbEnabled()
610
    {
611
        if ($this->mysql_enabled) {
612
            return true;
613
        } else {
614
            return false;
615
        }
616
    }
617
618
    /**
619
     * Add a single custom commands path
620
     *
621
     * @param string $path Custom commands path to add
622
     * @param bool $before If the path should be prepended or appended to the list
623
     *
624
     * @return \Longman\TelegramBot\Telegram
625
     */
626 32
    public function addCommandsPath($path, $before = true)
627
    {
628 32
        if (! is_dir($path)) {
629 1
            TelegramLog::error('Commands path "%s" does not exist.', $path);
630 32
        } else if (! in_array($path, $this->commands_paths, true)) {
631 32
            if ($before) {
632 32
                array_unshift($this->commands_paths, $path);
633
            } else {
634
                $this->commands_paths[] = $path;
635
            }
636
        }
637
638 32
        return $this;
639
    }
640
641
    /**
642
     * Add multiple custom commands paths
643
     *
644
     * @param array $paths Custom commands paths to add
645
     * @param bool $before If the paths should be prepended or appended to the list
646
     *
647
     * @return \Longman\TelegramBot\Telegram
648
     */
649 1
    public function addCommandsPaths(array $paths, $before = true)
650
    {
651 1
        foreach ($paths as $path) {
652 1
            $this->addCommandsPath($path, $before);
653
        }
654
655 1
        return $this;
656
    }
657
658
    /**
659
     * Return the list of commands paths
660
     *
661
     * @return array
662
     */
663 1
    public function getCommandsPaths()
664
    {
665 1
        return $this->commands_paths;
666
    }
667
668
    /**
669
     * Set custom upload path
670
     *
671
     * @param string $path Custom upload path
672
     *
673
     * @return \Longman\TelegramBot\Telegram
674
     */
675
    public function setUploadPath($path)
676
    {
677
        $this->upload_path = $path;
678
679
        return $this;
680
    }
681
682
    /**
683
     * Get custom upload path
684
     *
685
     * @return string
686
     */
687
    public function getUploadPath()
688
    {
689
        return $this->upload_path;
690
    }
691
692
    /**
693
     * Set custom download path
694
     *
695
     * @param string $path Custom download path
696
     *
697
     * @return \Longman\TelegramBot\Telegram
698
     */
699
    public function setDownloadPath($path)
700
    {
701
        $this->download_path = $path;
702
703
        return $this;
704
    }
705
706
    /**
707
     * Get custom download path
708
     *
709
     * @return string
710
     */
711
    public function getDownloadPath()
712
    {
713
        return $this->download_path;
714
    }
715
716
    /**
717
     * Set command config
718
     *
719
     * Provide further variables to a particular commands.
720
     * For example you can add the channel name at the command /sendtochannel
721
     * Or you can add the api key for external service.
722
     *
723
     * @param string $command
724
     * @param array $config
725
     *
726
     * @return \Longman\TelegramBot\Telegram
727
     */
728 14
    public function setCommandConfig($command, array $config)
729
    {
730 14
        $this->commands_config[$command] = $config;
731
732 14
        return $this;
733
    }
734
735
    /**
736
     * Get command config
737
     *
738
     * @param string $command
739
     *
740
     * @return array
741
     */
742 16
    public function getCommandConfig($command)
743
    {
744 16
        return isset($this->commands_config[$command]) ? $this->commands_config[$command] : [];
745
    }
746
747
    /**
748
     * Get API key
749
     *
750
     * @return string
751
     */
752 1
    public function getApiKey()
753
    {
754 1
        return $this->api_key;
755
    }
756
757
    /**
758
     * Get Bot name
759
     *
760
     * @return string
761
     */
762 2
    public function getBotUsername()
763
    {
764 2
        return $this->bot_username;
765
    }
766
767
    /**
768
     * Get Bot Id
769
     *
770
     * @return string
771
     */
772
    public function getBotId()
773
    {
774
        return $this->bot_id;
775
    }
776
777
    /**
778
     * Get Version
779
     *
780
     * @return string
781
     */
782
    public function getVersion()
783
    {
784
        return self::VERSION;
785
    }
786
787
    /**
788
     * Set Webhook for bot
789
     *
790
     * @param string $url
791
     * @param array $data Optional parameters.
792
     *
793
     * @return \Longman\TelegramBot\Http\Response
794
     * @throws \Longman\TelegramBot\Exception\TelegramException
795
     */
796
    public function setWebhook($url, array $data = [])
797
    {
798
        if (empty($url)) {
799
            throw new TelegramException('Hook url is empty!');
800
        }
801
802
        $data = array_intersect_key($data, array_flip([
803
            'certificate',
804
            'max_connections',
805
            'allowed_updates',
806
        ]));
807
        $data['url'] = $url;
808
809
        // If the certificate is passed as a path, encode and add the file to the data array.
810
        if (! empty($data['certificate']) && is_string($data['certificate'])) {
811
            $data['certificate'] = Client::encodeFile($data['certificate']);
812
        }
813
814
        $result = Client::setWebhook($data);
815
816 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...
817
            throw new TelegramException(
818
                'Webhook was not set! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
819
            );
820
        }
821
822
        return $result;
823
    }
824
825
    /**
826
     * Delete any assigned webhook
827
     *
828
     * @return mixed
829
     * @throws \Longman\TelegramBot\Exception\TelegramException
830
     */
831
    public function deleteWebhook()
832
    {
833
        $result = Client::deleteWebhook();
834
835 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...
836
            throw new TelegramException(
837
                'Webhook was not deleted! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
838
            );
839
        }
840
841
        return $result;
842
    }
843
844
    /**
845
     * Replace function `ucwords` 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 2
    protected function ucwordsUnicode($str, $encoding = 'UTF-8')
853
    {
854 2
        return mb_convert_case($str, MB_CASE_TITLE, $encoding);
855
    }
856
857
    /**
858
     * Replace function `ucfirst` for UTF-8 characters in the class definition and commands
859
     *
860
     * @param string $str
861
     * @param string $encoding (default = 'UTF-8')
862
     *
863
     * @return string
864
     */
865 2
    protected function ucfirstUnicode($str, $encoding = 'UTF-8')
866
    {
867 2
        return mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding)
868 2
            . mb_strtolower(mb_substr($str, 1, mb_strlen($str), $encoding), $encoding);
869
    }
870
871
    /**
872
     * Enable Botan.io integration
873
     *
874
     * @param  string $token
875
     * @param  array $options
876
     *
877
     * @return \Longman\TelegramBot\Telegram
878
     * @throws \Longman\TelegramBot\Exception\TelegramException
879
     */
880
    public function enableBotan($token, array $options = [])
881
    {
882
        Botan::initializeBotan($token, $options);
883
        $this->botan_enabled = true;
884
885
        return $this;
886
    }
887
888
    /**
889
     * Enable requests limiter
890
     *
891
     * @param  array $options
892
     *
893
     * @return \Longman\TelegramBot\Telegram
894
     */
895
    public function enableLimiter(array $options = [])
896
    {
897
        Client::setLimiter(true, $options);
898
899
        return $this;
900
    }
901
902
    /**
903
     * Run provided commands
904
     *
905
     * @param array $commands
906
     *
907
     * @throws TelegramException
908
     */
909
    public function runCommands($commands)
910
    {
911
        if (! is_array($commands) || empty($commands)) {
912
            throw new TelegramException('No command(s) provided!');
913
        }
914
915
        $this->run_commands = true;
916
        $this->botan_enabled = false;   // Force disable Botan.io integration, we don't want to track self-executed commands!
917
918
        $result = Client::getMe();
919
920
        if ($result->isOk()) {
921
            $result = $result->getResult();
922
923
            $bot_id = $result->getId();
924
            $bot_name = $result->getFirstName();
925
            $bot_username = $result->getUsername();
926
        } else {
927
            $bot_id = $this->getBotId();
928
            $bot_name = $this->getBotUsername();
929
            $bot_username = $this->getBotUsername();
930
        }
931
932
        $this->enableAdmin($bot_id);    // Give bot access to admin commands
933
        $this->getCommandsList();       // Load full commands list
934
935
        foreach ($commands as $command) {
936
            $this->update = new Update(
937
                [
938
                    'update_id' => 0,
939
                    'message'   => [
940
                        'message_id' => 0,
941
                        'from'       => [
942
                            'id'         => $bot_id,
943
                            'first_name' => $bot_name,
944
                            'username'   => $bot_username,
945
                        ],
946
                        'date'       => time(),
947
                        'chat'       => [
948
                            'id'   => $bot_id,
949
                            'type' => 'private',
950
                        ],
951
                        'text'       => $command,
952
                    ],
953
                ]
954
            );
955
956
            $this->executeCommand($this->update->getMessage()->getCommand());
957
        }
958
    }
959
960
    /**
961
     * Is this session initiated by runCommands()
962
     *
963
     * @return bool
964
     */
965
    public function isRunCommands()
966
    {
967
        return $this->run_commands;
968
    }
969
970
    /**
971
     * Switch to enable running getUpdates without a database
972
     *
973
     * @param bool $enable
974
     */
975
    public function useGetUpdatesWithoutDatabase($enable = true)
976
    {
977
        $this->getupdates_without_database = $enable;
978
    }
979
980
    /**
981
     * Return last update id
982
     *
983
     * @return int
984
     */
985
    public function getLastUpdateId()
986
    {
987
        return $this->last_update_id;
988
    }
989
}
990