Completed
Pull Request — develop (#756)
by
unknown
07:43
created

Telegram::addNamespaces()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
  /**
3
   * This file is part of the TelegramBot package.
4
   *
5
   * (c) Avtandil Kikabidze aka LONGMAN <[email protected]>
6
   *
7
   * For the full copyright and license information, please view the LICENSE
8
   * file that was distributed with this source code.
9
   */
10
  
11
  namespace Longman\TelegramBot;
12
  
13 1
  define('BASE_PATH', __DIR__);
14 1
  define('BASE_COMMANDS_PATH', BASE_PATH . '/Commands');
15
  
16
  use Exception;
17
  use Longman\TelegramBot\Commands\Command;
18
  use Longman\TelegramBot\Entities\ServerResponse;
19
  use Longman\TelegramBot\Entities\Update;
20
  use Longman\TelegramBot\Exception\TelegramException;
21
  use PDO;
22
  use RecursiveDirectoryIterator;
23
  use RecursiveIteratorIterator;
24
  use RegexIterator;
25
  
26
  class Telegram
27
  {
28
    /**
29
     * Version
30
     *
31
     * @var string
32
     */
33
    protected $version = '0.52.0';
34
    
35
    /**
36
     * Telegram API key
37
     *
38
     * @var string
39
     */
40
    protected $api_key = '';
41
    
42
    /**
43
     * Telegram Bot username
44
     *
45
     * @var string
46
     */
47
    protected $bot_username = '';
48
    
49
    /**
50
     * Telegram Bot id
51
     *
52
     * @var string
53
     */
54
    protected $bot_id = '';
55
    
56
    /**
57
     * Raw request data (json) for webhook methods
58
     *
59
     * @var string
60
     */
61
    protected $input;
62
    
63
    /**
64
     * Custom commands paths
65
     *
66
     * @var array
67
     */
68
    protected $commands_paths = [];
69
    
70
    /**
71
     * Current Update object
72
     *
73
     * @var \Longman\TelegramBot\Entities\Update
74
     */
75
    protected $update;
76
    
77
    /**
78
     * Upload path
79
     *
80
     * @var string
81
     */
82
    protected $upload_path;
83
    
84
    /**
85
     * Download path
86
     *
87
     * @var string
88
     */
89
    protected $download_path;
90
    
91
    /**
92
     * MySQL integration
93
     *
94
     * @var boolean
95
     */
96
    protected $mysql_enabled = FALSE;
97
    
98
    /**
99
     * PDO object
100
     *
101
     * @var \PDO
102
     */
103
    protected $pdo;
104
    
105
    /**
106
     * Commands config
107
     *
108
     * @var array
109
     */
110
    protected $commands_config = [];
111
    
112
    /**
113
     * Admins list
114
     *
115
     * @var array
116
     */
117
    protected $admins_list = [];
118
    
119
    /**
120
     * ServerResponse of the last Command execution
121
     *
122
     * @var \Longman\TelegramBot\Entities\ServerResponse
123
     */
124
    protected $last_command_response;
125
    
126
    /**
127
     * Botan.io integration
128
     *
129
     * @var boolean
130
     */
131
    protected $botan_enabled = FALSE;
132
    
133
    /**
134
     * Check if runCommands() is running in this session
135
     *
136
     * @var boolean
137
     */
138
    protected $run_commands = FALSE;
139
    
140
    /**
141
     * Custom Namespaces
142
     *
143
     * @var array
144
     */
145
    protected $custom_namespaces = [];
146
    
147
    /**
148
     * Telegram constructor.
149
     *
150
     * @param string $api_key
151
     * @param string $bot_username
152
     *
153
     * @throws \Longman\TelegramBot\Exception\TelegramException
154
     */
155 30
    public function __construct($api_key, $bot_username = '')
156
    {
157 30
      if (empty($api_key)) {
158 1
        throw new TelegramException('API KEY not defined!');
159
      }
160 30
      preg_match('/(\d+)\:[\w\-]+/', $api_key, $matches);
161 30
      if (!isset($matches[1])) {
162 1
        throw new TelegramException('Invalid API KEY defined!');
163
      }
164 30
      $this->bot_id  = $matches[1];
165 30
      $this->api_key = $api_key;
166
      
167 30
      if (!empty($bot_username)) {
168 30
        $this->bot_username = $bot_username;
169
      }
170
      
171
      //Add default system commands path
172 30
      $this->addCommandsPath(BASE_COMMANDS_PATH . '/SystemCommands');
173
      
174 30
      Request::initialize($this);
175 30
    }
176
    
177
    /**
178
     * Initialize Database connection
179
     *
180
     * @param array  $credential
181
     * @param string $table_prefix
182
     * @param string $encoding
183
     *
184
     * @return \Longman\TelegramBot\Telegram
185
     * @throws \Longman\TelegramBot\Exception\TelegramException
186
     */
187 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...
188
    {
189 9
      $this->pdo = DB::initialize($credential, $this, $table_prefix, $encoding);
190 9
      ConversationDB::initializeConversation();
191 9
      $this->mysql_enabled = TRUE;
192
      
193 9
      return $this;
194
    }
195
    
196
    public function addNamespaces(array $namespaces = [])
197
    {
198
      $this->custom_namespaces = $namespaces;
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 1
          $files = new RegexIterator(
233 1
            new RecursiveIteratorIterator(
234 1
              new RecursiveDirectoryIterator($path)
235
            ),
236 1
            '/^.+Command.php$/'
237
          );
238
          
239 1
          foreach ($files as $file) {
240
            //Remove "Command.php" from filename
241 1
            $command      = $this->sanitizeCommand(substr($file->getFilename(), 0, -11));
242 1
            $command_name = strtolower($command);
243
            
244 1
            if (array_key_exists($command_name, $commands)) {
245
              continue;
246
            }
247
            
248 1
            require_once $file->getPathname();
249
            
250 1
            $command_obj = $this->getCommandObject($command);
251 1
            if ($command_obj instanceof Command) {
252 1
              $commands[ $command_name ] = $command_obj;
253
            }
254
          }
255
        } catch (Exception $e) {
256 1
          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 1
    public function getCommandObject($command)
271
    {
272 1
      $which = ['System'];
273 1
      $this->isAdmin() && $which[] = 'Admin';
274 1
      $which[] = 'User';
275
      
276 1
      if (count($this->custom_namespaces) >= 1) {
277
        foreach ($this->custom_namespaces as $custom_namespace) {
278
          $command_namespace = $custom_namespace . '\\' . $this->ucfirstUnicode($command) . 'Command';
279
          if (class_exists($command_namespace)) {
280
            return new $command_namespace($this, $this->update);
281
          }
282
        }
283
      }
284
      
285 1
      foreach ($which as $auth) {
286 1
        $command_namespace = __NAMESPACE__ . '\\Commands\\' . $auth . 'Commands\\' . $this->ucfirstUnicode($command) . 'Command';
287 1
        if (class_exists($command_namespace)) {
288 1
          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()) {
345
        return new ServerResponse(
346
          [
347
            'ok'          => FALSE,
348
            'description' => 'getUpdates needs MySQL connection!',
349
          ],
350
          $this->bot_username
351
        );
352
      }
353
      
354
      //Take custom input into account.
355
      if ($custom_input = $this->getCustomInput()) {
356
        $response = new ServerResponse(json_decode($custom_input, TRUE), $this->bot_username);
357
      } else {
358
        //DB Query
359
        $last_update = DB::selectTelegramUpdate(1);
360
        $last_update = reset($last_update);
361
        
362
        //As explained in the telegram bot api documentation
363
        $offset = isset($last_update['id']) ? $last_update['id'] + 1 : NULL;
364
        
365
        $response = Request::getUpdates(
366
          [
367
            'offset'  => $offset,
368
            'limit'   => $limit,
369
            'timeout' => $timeout,
370
          ]
371
        );
372
      }
373
      
374
      if ($response->isOk()) {
375
        //Process all updates
376
        /** @var Update $result */
377
        foreach ((array)$response->getResult() as $result) {
378
          $this->processUpdate($result);
379
        }
380
      }
381
      
382
      return $response;
383
    }
384
    
385
    /**
386
     * Handle bot request from webhook
387
     *
388
     * @return bool
389
     *
390
     * @throws \Longman\TelegramBot\Exception\TelegramException
391
     */
392
    public function handle()
393
    {
394
      if (empty($this->bot_username)) {
395
        throw new TelegramException('Bot Username is not defined!');
396
      }
397
      
398
      $this->input = Request::getInput();
399
      
400
      if (empty($this->input)) {
401
        throw new TelegramException('Input is empty!');
402
      }
403
      
404
      $post = json_decode($this->input, TRUE);
405
      if (empty($post)) {
406
        throw new TelegramException('Invalid JSON!');
407
      }
408
      
409
      if ($response = $this->processUpdate(new Update($post, $this->bot_username))) {
410
        return $response->isOk();
411
      }
412
      
413
      return FALSE;
414
    }
415
    
416
    /**
417
     * Get the command name from the command type
418
     *
419
     * @param string $type
420
     *
421
     * @return string
422
     */
423
    protected function getCommandFromType($type)
424
    {
425
      return $this->ucfirstUnicode(str_replace('_', '', $type));
426
    }
427
    
428
    /**
429
     * Process bot Update request
430
     *
431
     * @param \Longman\TelegramBot\Entities\Update $update
432
     *
433
     * @return \Longman\TelegramBot\Entities\ServerResponse
434
     * @throws \Longman\TelegramBot\Exception\TelegramException
435
     */
436
    public function processUpdate(Update $update)
437
    {
438
      $this->update = $update;
439
      
440
      //If all else fails, it's a generic message.
441
      $command = 'genericmessage';
442
      
443
      $update_type = $this->update->getUpdateType();
444
      if ($update_type === 'message') {
445
        $message = $this->update->getMessage();
446
        
447
        //Load admin commands
448
        if ($this->isAdmin()) {
449
          $this->addCommandsPath(BASE_COMMANDS_PATH . '/AdminCommands', FALSE);
450
        }
451
        
452
        $type = $message->getType();
453
        if ($type === 'command') {
454
          $command = $message->getCommand();
455
        } elseif (in_array($type, [
456
          'new_chat_members',
457
          'left_chat_member',
458
          'new_chat_title',
459
          'new_chat_photo',
460
          'delete_chat_photo',
461
          'group_chat_created',
462
          'supergroup_chat_created',
463
          'channel_chat_created',
464
          'migrate_to_chat_id',
465
          'migrate_from_chat_id',
466
          'pinned_message',
467
          'invoice',
468
          'successful_payment',
469
        ], TRUE)
470
        ) {
471
          $command = $this->getCommandFromType($type);
472
        }
473
      } else {
474
        $command = $this->getCommandFromType($update_type);
475
      }
476
      
477
      //Make sure we have an up-to-date command list
478
      //This is necessary to "require" all the necessary command files!
479
      $this->getCommandsList();
480
      
481
      DB::insertRequest($this->update);
482
      
483
      return $this->executeCommand($command);
484
    }
485
    
486
    /**
487
     * Execute /command
488
     *
489
     * @param string $command
490
     *
491
     * @return mixed
492
     * @throws \Longman\TelegramBot\Exception\TelegramException
493
     */
494
    public function executeCommand($command)
495
    {
496
      $command     = strtolower($command);
497
      $command_obj = $this->getCommandObject($command);
498
      
499
      if (!$command_obj || !$command_obj->isEnabled()) {
500
        //Failsafe in case the Generic command can't be found
501
        if ($command === 'generic') {
502
          throw new TelegramException('Generic command missing!');
503
        }
504
        
505
        //Handle a generic command or non existing one
506
        $this->last_command_response = $this->executeCommand('generic');
507
      } else {
508
        //Botan.io integration, make sure only the actual command user executed is reported
509
        if ($this->botan_enabled) {
510
          Botan::lock($command);
511
        }
512
        
513
        //execute() method is executed after preExecute()
514
        //This is to prevent executing a DB query without a valid connection
515
        $this->last_command_response = $command_obj->preExecute();
516
        
517
        //Botan.io integration, send report after executing the command
518
        if ($this->botan_enabled) {
519
          Botan::track($this->update, $command);
520
        }
521
      }
522
      
523
      return $this->last_command_response;
524
    }
525
    
526
    /**
527
     * Sanitize Command
528
     *
529
     * @param string $command
530
     *
531
     * @return string
532
     */
533 1
    protected function sanitizeCommand($command)
534
    {
535 1
      return str_replace(' ', '', $this->ucwordsUnicode(str_replace('_', ' ', $command)));
536
    }
537
    
538
    /**
539
     * Enable a single Admin account
540
     *
541
     * @param integer $admin_id Single admin id
542
     *
543
     * @return \Longman\TelegramBot\Telegram
544
     */
545 1
    public function enableAdmin($admin_id)
546
    {
547 1
      if (!is_int($admin_id) || $admin_id <= 0) {
548 1
        TelegramLog::error('Invalid value "%s" for admin.', $admin_id);
549 1
      } elseif (!in_array($admin_id, $this->admins_list, TRUE)) {
550 1
        $this->admins_list[] = $admin_id;
551
      }
552
      
553 1
      return $this;
554
    }
555
    
556
    /**
557
     * Enable a list of Admin Accounts
558
     *
559
     * @param array $admin_ids List of admin ids
560
     *
561
     * @return \Longman\TelegramBot\Telegram
562
     */
563 1
    public function enableAdmins(array $admin_ids)
564
    {
565 1
      foreach ($admin_ids as $admin_id) {
566 1
        $this->enableAdmin($admin_id);
567
      }
568
      
569 1
      return $this;
570
    }
571
    
572
    /**
573
     * Get list of admins
574
     *
575
     * @return array
576
     */
577 1
    public function getAdminList()
578
    {
579 1
      return $this->admins_list;
580
    }
581
    
582
    /**
583
     * Check if the passed user is an admin
584
     *
585
     * If no user id is passed, the current update is checked for a valid message sender.
586
     *
587
     * @param int|null $user_id
588
     *
589
     * @return bool
590
     */
591 1
    public function isAdmin($user_id = NULL)
592
    {
593 1
      if ($user_id === NULL && $this->update !== NULL) {
594
        //Try to figure out if the user is an admin
595
        $update_methods = [
596
          'getMessage',
597
          'getEditedMessage',
598
          'getChannelPost',
599
          'getEditedChannelPost',
600
          'getInlineQuery',
601
          'getChosenInlineResult',
602
          'getCallbackQuery',
603
        ];
604
        foreach ($update_methods as $update_method) {
605
          $object = call_user_func([$this->update, $update_method]);
606
          if ($object !== NULL && $from = $object->getFrom()) {
607
            $user_id = $from->getId();
608
            break;
609
          }
610
        }
611
      }
612
      
613 1
      return ($user_id === NULL) ? FALSE : in_array($user_id, $this->admins_list, TRUE);
614
    }
615
    
616
    /**
617
     * Check if user required the db connection
618
     *
619
     * @return bool
620
     */
621
    public function isDbEnabled()
622
    {
623
      if ($this->mysql_enabled) {
624
        return TRUE;
625
      } else {
626
        return FALSE;
627
      }
628
    }
629
    
630
    /**
631
     * Add a single custom commands path
632
     *
633
     * @param string $path   Custom commands path to add
634
     * @param bool   $before If the path should be prepended or appended to the list
635
     *
636
     * @return \Longman\TelegramBot\Telegram
637
     */
638 30
    public function addCommandsPath($path, $before = TRUE)
639
    {
640 30
      if (!is_dir($path)) {
641 1
        TelegramLog::error('Commands path "%s" does not exist.', $path);
642 30
      } elseif (!in_array($path, $this->commands_paths, TRUE)) {
643 30
        if ($before) {
644 30
          array_unshift($this->commands_paths, $path);
645
        } else {
646
          $this->commands_paths[] = $path;
647
        }
648
      }
649
      
650 30
      return $this;
651
    }
652
    
653
    /**
654
     * Add multiple custom commands paths
655
     *
656
     * @param array $paths  Custom commands paths to add
657
     * @param bool  $before If the paths should be prepended or appended to the list
658
     *
659
     * @return \Longman\TelegramBot\Telegram
660
     */
661 1
    public function addCommandsPaths(array $paths, $before = TRUE)
662
    {
663 1
      foreach ($paths as $path) {
664 1
        $this->addCommandsPath($path, $before);
665
      }
666
      
667 1
      return $this;
668
    }
669
    
670
    /**
671
     * Return the list of commands paths
672
     *
673
     * @return array
674
     */
675 1
    public function getCommandsPaths()
676
    {
677 1
      return $this->commands_paths;
678
    }
679
    
680
    /**
681
     * Set custom upload path
682
     *
683
     * @param string $path Custom upload path
684
     *
685
     * @return \Longman\TelegramBot\Telegram
686
     */
687
    public function setUploadPath($path)
688
    {
689
      $this->upload_path = $path;
690
      
691
      return $this;
692
    }
693
    
694
    /**
695
     * Get custom upload path
696
     *
697
     * @return string
698
     */
699
    public function getUploadPath()
700
    {
701
      return $this->upload_path;
702
    }
703
    
704
    /**
705
     * Set custom download path
706
     *
707
     * @param string $path Custom download path
708
     *
709
     * @return \Longman\TelegramBot\Telegram
710
     */
711
    public function setDownloadPath($path)
712
    {
713
      $this->download_path = $path;
714
      
715
      return $this;
716
    }
717
    
718
    /**
719
     * Get custom download path
720
     *
721
     * @return string
722
     */
723
    public function getDownloadPath()
724
    {
725
      return $this->download_path;
726
    }
727
    
728
    /**
729
     * Set command config
730
     *
731
     * Provide further variables to a particular commands.
732
     * For example you can add the channel name at the command /sendtochannel
733
     * Or you can add the api key for external service.
734
     *
735
     * @param string $command
736
     * @param array  $config
737
     *
738
     * @return \Longman\TelegramBot\Telegram
739
     */
740 14
    public function setCommandConfig($command, array $config)
741
    {
742 14
      $this->commands_config[ $command ] = $config;
743
      
744 14
      return $this;
745
    }
746
    
747
    /**
748
     * Get command config
749
     *
750
     * @param string $command
751
     *
752
     * @return array
753
     */
754 15
    public function getCommandConfig($command)
755
    {
756 15
      return isset($this->commands_config[ $command ]) ? $this->commands_config[ $command ] : [];
757
    }
758
    
759
    /**
760
     * Get API key
761
     *
762
     * @return string
763
     */
764 1
    public function getApiKey()
765
    {
766 1
      return $this->api_key;
767
    }
768
    
769
    /**
770
     * Get Bot name
771
     *
772
     * @return string
773
     */
774 1
    public function getBotUsername()
775
    {
776 1
      return $this->bot_username;
777
    }
778
    
779
    /**
780
     * Get Bot Id
781
     *
782
     * @return string
783
     */
784
    public function getBotId()
785
    {
786
      return $this->bot_id;
787
    }
788
    
789
    /**
790
     * Get Version
791
     *
792
     * @return string
793
     */
794
    public function getVersion()
795
    {
796
      return $this->version;
797
    }
798
    
799
    /**
800
     * Set Webhook for bot
801
     *
802
     * @param string $url
803
     * @param array  $data Optional parameters.
804
     *
805
     * @return \Longman\TelegramBot\Entities\ServerResponse
806
     * @throws \Longman\TelegramBot\Exception\TelegramException
807
     */
808
    public function setWebhook($url, array $data = [])
809
    {
810
      if (empty($url)) {
811
        throw new TelegramException('Hook url is empty!');
812
      }
813
      
814
      $data        = array_intersect_key($data, array_flip([
815
        'certificate',
816
        'max_connections',
817
        'allowed_updates',
818
      ]));
819
      $data['url'] = $url;
820
      
821
      // If the certificate is passed as a path, encode and add the file to the data array.
822
      if (!empty($data['certificate']) && is_string($data['certificate'])) {
823
        $data['certificate'] = Request::encodeFile($data['certificate']);
824
      }
825
      
826
      $result = Request::setWebhook($data);
827
      
828 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...
829
        throw new TelegramException(
830
          'Webhook was not set! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
831
        );
832
      }
833
      
834
      return $result;
835
    }
836
    
837
    /**
838
     * Delete any assigned webhook
839
     *
840
     * @return mixed
841
     * @throws \Longman\TelegramBot\Exception\TelegramException
842
     */
843
    public function deleteWebhook()
844
    {
845
      $result = Request::deleteWebhook();
846
      
847 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...
848
        throw new TelegramException(
849
          'Webhook was not deleted! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription()
850
        );
851
      }
852
      
853
      return $result;
854
    }
855
    
856
    /**
857
     * Replace function `ucwords` for UTF-8 characters in the class definition and commands
858
     *
859
     * @param string $str
860
     * @param string $encoding (default = 'UTF-8')
861
     *
862
     * @return string
863
     */
864 1
    protected function ucwordsUnicode($str, $encoding = 'UTF-8')
865
    {
866 1
      return mb_convert_case($str, MB_CASE_TITLE, $encoding);
867
    }
868
    
869
    /**
870
     * Replace function `ucfirst` for UTF-8 characters in the class definition and commands
871
     *
872
     * @param string $str
873
     * @param string $encoding (default = 'UTF-8')
874
     *
875
     * @return string
876
     */
877 1
    protected function ucfirstUnicode($str, $encoding = 'UTF-8')
878
    {
879
      return
880 1
        mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding)
881 1
        . mb_strtolower(mb_substr($str, 1, mb_strlen($str), $encoding), $encoding);
882
    }
883
    
884
    /**
885
     * Enable Botan.io integration
886
     *
887
     * @param  string $token
888
     * @param  array  $options
889
     *
890
     * @return \Longman\TelegramBot\Telegram
891
     * @throws \Longman\TelegramBot\Exception\TelegramException
892
     */
893
    public function enableBotan($token, array $options = [])
894
    {
895
      Botan::initializeBotan($token, $options);
896
      $this->botan_enabled = TRUE;
897
      
898
      return $this;
899
    }
900
    
901
    /**
902
     * Enable requests limiter
903
     *
904
     * @param  array $options
905
     *
906
     * @return \Longman\TelegramBot\Telegram
907
     */
908
    public function enableLimiter(array $options = [])
909
    {
910
      Request::setLimiter(TRUE, $options);
911
      
912
      return $this;
913
    }
914
    
915
    /**
916
     * Run provided commands
917
     *
918
     * @param array $commands
919
     *
920
     * @throws TelegramException
921
     */
922
    public function runCommands($commands)
923
    {
924
      if (!is_array($commands) || empty($commands)) {
925
        throw new TelegramException('No command(s) provided!');
926
      }
927
      
928
      $this->run_commands  = TRUE;
929
      $this->botan_enabled = FALSE;   // Force disable Botan.io integration, we don't want to track self-executed commands!
930
      
931
      $result = Request::getMe();
932
      
933
      if ($result->isOk()) {
934
        $result = $result->getResult();
935
        
936
        $bot_id       = $result->getId();
937
        $bot_name     = $result->getFirstName();
938
        $bot_username = $result->getUsername();
939
      } else {
940
        $bot_id       = $this->getBotId();
941
        $bot_name     = $this->getBotUsername();
942
        $bot_username = $this->getBotUsername();
943
      }
944
      
945
      
946
      $this->enableAdmin($bot_id);    // Give bot access to admin commands
947
      $this->getCommandsList();       // Load full commands list
948
      
949
      foreach ($commands as $command) {
950
        $this->update = new Update(
951
          [
952
            'update_id' => 0,
953
            'message'   => [
954
              'message_id' => 0,
955
              'from'       => [
956
                'id'         => $bot_id,
957
                'first_name' => $bot_name,
958
                'username'   => $bot_username,
959
              ],
960
              'date'       => time(),
961
              'chat'       => [
962
                'id'   => $bot_id,
963
                'type' => 'private',
964
              ],
965
              'text'       => $command,
966
            ],
967
          ]
968
        );
969
        
970
        $this->executeCommand($this->update->getMessage()->getCommand());
971
      }
972
    }
973
    
974
    /**
975
     * Is this session initiated by runCommands()
976
     *
977
     * @return bool
978
     */
979
    public function isRunCommands()
980
    {
981
      return $this->run_commands;
982
    }
983
  }
984