Completed
Push — master ( d35303...21e214 )
by Irfaq
02:49
created

Api::emojify()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.0261

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 11
ccs 6
cts 7
cp 0.8571
rs 9.4285
cc 3
eloc 6
nc 3
nop 2
crap 3.0261
1
<?php
2
3
namespace Telegram\Bot;
4
5
use Illuminate\Contracts\Container\Container;
6
use Telegram\Bot\Commands\CommandBus;
7
use Telegram\Bot\Exceptions\TelegramSDKException;
8
use Telegram\Bot\FileUpload\InputFile;
9
use Telegram\Bot\HttpClients\GuzzleHttpClient;
10
use Telegram\Bot\HttpClients\HttpClientInterface;
11
use Telegram\Bot\Objects\File;
12
use Telegram\Bot\Objects\Message;
13
use Telegram\Bot\Objects\UnknownObject;
14
use Telegram\Bot\Objects\Update;
15
use Telegram\Bot\Objects\User;
16
use Telegram\Bot\Objects\UserProfilePhotos;
17
use Telegram\Bot\Keyboard\Keyboard;
18
19
/**
20
 * Class Api.
21
 *
22
 * @mixin Commands\CommandBus
23
 */
24
class Api
25
{
26
    /**
27
     * @var string Version number of the Telegram Bot PHP SDK.
28
     */
29
    const VERSION = '3.0.0';
30
31
    /**
32
     * @var string The name of the environment variable that contains the Telegram Bot API Access Token.
33
     */
34
    const BOT_TOKEN_ENV_NAME = 'TELEGRAM_BOT_TOKEN';
35
36
    /**
37
     * @var TelegramClient The Telegram client service.
38
     */
39
    protected $client;
40
41
    /**
42
     * @var string Telegram Bot API Access Token.
43
     */
44
    protected $accessToken = null;
45
46
    /**
47
     * @var TelegramResponse|null Stores the last request made to Telegram Bot API.
48
     */
49
    protected $lastResponse;
50
51
    /**
52
     * @var bool Indicates if the request to Telegram will be asynchronous (non-blocking).
53
     */
54
    protected $isAsyncRequest = false;
55
56
    /**
57
     * @var CommandBus|null Telegram Command Bus.
58
     */
59
    protected $commandBus = null;
60
61
    /**
62
     * @var Container IoC Container
63
     */
64
    protected static $container = null;
65
66
    /**
67
     * Timeout of the request in seconds.
68
     *
69
     * @var int
70
     */
71
    protected $timeOut = 60;
72
73
    /**
74
     * Connection timeout of the request in seconds.
75
     *
76
     * @var int
77
     */
78
    protected $connectTimeOut = 10;
79
80
    /**
81
     * Instantiates a new Telegram super-class object.
82
     *
83
     *
84
     * @param string              $token                      The Telegram Bot API Access Token.
85
     * @param bool                $async                      (Optional) Indicates if the request to Telegram
86
     *                                                        will be asynchronous (non-blocking).
87
     * @param HttpClientInterface $httpClientHandler          (Optional) Custom HTTP Client Handler.
88
     *
89
     * @throws TelegramSDKException
90
     */
91 66
    public function __construct($token = null, $async = false, $httpClientHandler = null)
92
    {
93 66
        $this->accessToken = isset($token) ? $token : getenv(static::BOT_TOKEN_ENV_NAME);
94 66
        if (!$this->accessToken) {
95 2
            throw new TelegramSDKException('Required "token" not supplied in config and could not find fallback environment variable "'.static::BOT_TOKEN_ENV_NAME.'"');
96
        }
97
98 66
        if (isset($async)) {
99 66
            $this->setAsyncRequest($async);
100 66
        }
101
102 66
        $this->client = new TelegramClient($httpClientHandler);
103 66
        $this->commandBus = new CommandBus($this);
104 66
    }
105
106
    /**
107
     * Invoke Bots Manager.
108
     *
109
     * @param $config
110
     *
111
     * @return BotsManager
112
     */
113
    public static function manager($config)
114
    {
115
        return new BotsManager($config);
116
    }
117
118
    /**
119
     * Returns the TelegramClient service.
120
     *
121
     * @return TelegramClient
122
     */
123 6
    public function getClient()
124
    {
125 6
        return $this->client;
126
    }
127
128
    /**
129
     * Returns Telegram Bot API Access Token.
130
     *
131
     * @return string
132
     */
133 42
    public function getAccessToken()
134
    {
135 42
        return $this->accessToken;
136
    }
137
138
    /**
139
     * Returns the last response returned from API request.
140
     *
141
     * @return TelegramResponse
142
     */
143 2
    public function getLastResponse()
144
    {
145 2
        return $this->lastResponse;
146
    }
147
148
    /**
149
     * Sets the bot access token to use with API requests.
150
     *
151
     * @param string $accessToken The bot access token to save.
152
     *
153
     * @throws \InvalidArgumentException
154
     *
155
     * @return Api
156
     */
157 8
    public function setAccessToken($accessToken)
158
    {
159 8
        if (is_string($accessToken)) {
160 2
            $this->accessToken = $accessToken;
161
162 2
            return $this;
163
        }
164
165 6
        throw new \InvalidArgumentException('The Telegram bot access token must be of type "string"');
166
    }
167
168
    /**
169
     * Make this request asynchronous (non-blocking).
170
     *
171
     * @param bool $isAsyncRequest
172
     *
173
     * @return Api
174
     */
175 66
    public function setAsyncRequest($isAsyncRequest)
176
    {
177 66
        $this->isAsyncRequest = $isAsyncRequest;
178
179 66
        return $this;
180
    }
181
182
    /**
183
     * Check if this is an asynchronous request (non-blocking).
184
     *
185
     * @return bool
186
     */
187 42
    public function isAsyncRequest()
188
    {
189 42
        return $this->isAsyncRequest;
190
    }
191
192
    /**
193
     * Returns SDK's Command Bus.
194
     *
195
     * @return CommandBus
196
     */
197 8
    public function getCommandBus()
198
    {
199 8
        return $this->commandBus;
200
    }
201
202
    /**
203
     * A simple method for testing your bot's auth token.
204
     * Returns basic information about the bot in form of a User object.
205
     *
206
     * @link https://core.telegram.org/bots/api#getme
207
     *
208
     * @return User
209
     */
210 4
    public function getMe()
211
    {
212 4
        $response = $this->post('getMe');
213
214 2
        return new User($response->getDecodedBody());
215
    }
216
217
    /**
218
     * Send text messages.
219
     *
220
     * <code>
221
     * $params = [
222
     *   'chat_id'                  => '',
223
     *   'text'                     => '',
224
     *   'parse_mode'               => '',
225
     *   'disable_web_page_preview' => '',
226
     *   'disable_notification'     => '',
227
     *   'reply_to_message_id'      => '',
228
     *   'reply_markup'             => '',
229
     * ];
230
     * </code>
231
     *
232
     * @link https://core.telegram.org/bots/api#sendmessage
233
     *
234
     * @param array    $params
235
     *
236
     * @var int|string $params ['chat_id']
237
     * @var string     $params ['text']
238
     * @var string     $params ['parse_mode']
239
     * @var bool       $params ['disable_web_page_preview']
240
     * @var bool       $params ['disable_notification']
241
     * @var int        $params ['reply_to_message_id']
242
     * @var string     $params ['reply_markup']
243
     *
244
     * @return Message
245
     */
246 4
    public function sendMessage(array $params)
247
    {
248 4
        $response = $this->post('sendMessage', $params);
249
250 4
        return new Message($response->getDecodedBody());
251
    }
252
253
    /**
254
     * Forward messages of any kind.
255
     *
256
     * <code>
257
     * $params = [
258
     *   'chat_id'              => '',
259
     *   'from_chat_id'         => '',
260
     *   'disable_notification' => '',
261
     *   'message_id'           => '',
262
     * ];
263
     * </code>
264
     *
265
     * @link https://core.telegram.org/bots/api#forwardmessage
266
     *
267
     * @param array    $params
268
     *
269
     * @var int|string $params ['chat_id']
270
     * @var int        $params ['from_chat_id']
271
     * @var bool       $params ['disable_notification']
272
     * @var int        $params ['message_id']
273
     *
274
     * @return Message
275
     */
276 2
    public function forwardMessage(array $params)
277
    {
278 2
        $response = $this->post('forwardMessage', $params);
279
280 2
        return new Message($response->getDecodedBody());
281
    }
282
283
    /**
284
     * Send Photos.
285
     *
286
     * <code>
287
     * $params = [
288
     *   'chat_id'              => '',
289
     *   'photo'                => '',
290
     *   'caption'              => '',
291
     *   'disable_notification' => '',
292
     *   'reply_to_message_id'  => '',
293
     *   'reply_markup'         => '',
294
     * ];
295
     * </code>
296
     *
297
     * @link https://core.telegram.org/bots/api#sendphoto
298
     *
299
     * @param array    $params
300
     *
301
     * @var int|string $params ['chat_id']
302
     * @var string     $params ['photo']
303
     * @var string     $params ['caption']
304
     * @var bool       $params ['disable_notification']
305
     * @var int        $params ['reply_to_message_id']
306
     * @var string     $params ['reply_markup']
307
     *
308
     * @return Message
309
     */
310 4
    public function sendPhoto(array $params)
311
    {
312 4
        return $this->uploadFile('sendPhoto', $params);
313
    }
314
315
    /**
316
     * Send regular audio files.
317
     *
318
     * <code>
319
     * $params = [
320
     *   'chat_id'              => '',
321
     *   'audio'                => '',
322
     *   'duration'             => '',
323
     *   'performer'            => '',
324
     *   'title'                => '',
325
     *   'disable_notification' => '',
326
     *   'reply_to_message_id'  => '',
327
     *   'reply_markup'         => '',
328
     * ];
329
     * </code>
330
     *
331
     * @link https://core.telegram.org/bots/api#sendaudio
332
     *
333
     * @param array    $params
334
     *
335
     * @var int|string $params ['chat_id']
336
     * @var string     $params ['audio']
337
     * @var int        $params ['duration']
338
     * @var string     $params ['performer']
339
     * @var string     $params ['title']
340
     * @var bool       $params ['disable_notification']
341
     * @var int        $params ['reply_to_message_id']
342
     * @var string     $params ['reply_markup']
343
     *
344
     * @return Message
345
     */
346 2
    public function sendAudio(array $params)
347
    {
348 2
        return $this->uploadFile('sendAudio', $params);
349
    }
350
351
    /**
352
     * Send general files.
353
     *
354
     * <code>
355
     * $params = [
356
     *   'chat_id'              => '',
357
     *   'document'             => '',
358
     *   'caption'              => '',
359
     *   'disable_notification' => '',
360
     *   'reply_to_message_id'  => '',
361
     *   'reply_markup'         => '',
362
     * ];
363
     * </code>
364
     *
365
     * @link https://core.telegram.org/bots/api#senddocument
366
     *
367
     * @param array    $params
368
     *
369
     * @var int|string $params ['chat_id']
370
     * @var string     $params ['document']
371
     * @var string     $params ['caption']
372
     * @var bool       $params ['disable_notification']
373
     * @var int        $params ['reply_to_message_id']
374
     * @var string     $params ['reply_markup']
375
     *
376
     * @return Message
377
     */
378 2
    public function sendDocument(array $params)
379
    {
380 2
        return $this->uploadFile('sendDocument', $params);
381
    }
382
383
    /**
384
     * Send .webp stickers.
385
     *
386
     * <code>
387
     * $params = [
388
     *   'chat_id'              => '',
389
     *   'sticker'              => '',
390
     *   'disable_notification' => '',
391
     *   'reply_to_message_id'  => '',
392
     *   'reply_markup'         => '',
393
     * ];
394
     * </code>
395
     *
396
     * @link https://core.telegram.org/bots/api#sendsticker
397
     *
398
     * @param array    $params
399
     *
400
     * @var int|string $params ['chat_id']
401
     * @var string     $params ['sticker']
402
     * @var bool       $params ['disable_notification']
403
     * @var int        $params ['reply_to_message_id']
404
     * @var string     $params ['reply_markup']
405
     *
406
     * @throws TelegramSDKException
407
     *
408
     * @return Message
409
     */
410 2
    public function sendSticker(array $params)
411
    {
412 2
        if (is_file($params['sticker']) && (pathinfo($params['sticker'], PATHINFO_EXTENSION) !== 'webp')) {
413
            throw new TelegramSDKException('Invalid Sticker Provided. Supported Format: Webp');
414
        }
415
416 2
        return $this->uploadFile('sendSticker', $params);
417
    }
418
419
    /**
420
     * Send Video File, Telegram clients support mp4 videos (other formats may be sent as Document).
421
     *
422
     * <code>
423
     * $params = [
424
     *   'chat_id'              => '',
425
     *   'video'                => '',
426
     *   'duration'             => '',
427
     *   'width'                => '',
428
     *   'height'               => '',
429
     *   'caption'              => '',
430
     *   'disable_notification' => '',
431
     *   'reply_to_message_id'  => '',
432
     *   'reply_markup'         => '',
433
     * ];
434
     * </code>
435
     *
436
     * @see  sendDocument
437
     * @link https://core.telegram.org/bots/api#sendvideo
438
     *
439
     * @param array    $params
440
     *
441
     * @var int|string $params ['chat_id']
442
     * @var string     $params ['video']
443
     * @var int        $params ['duration']
444
     * @var int        $params ['width']
445
     * @var int        $params ['height']
446
     * @var string     $params ['caption']
447
     * @var bool       $params ['disable_notification']
448
     * @var int        $params ['reply_to_message_id']
449
     * @var string     $params ['reply_markup']
450
     *
451
     * @return Message
452
     */
453 2
    public function sendVideo(array $params)
454
    {
455 2
        return $this->uploadFile('sendVideo', $params);
456
    }
457
458
    /**
459
     * Send voice audio files.
460
     *
461
     * <code>
462
     * $params = [
463
     *   'chat_id'              => '',
464
     *   'voice'                => '',
465
     *   'duration'             => '',
466
     *   'disable_notification' => '',
467
     *   'reply_to_message_id'  => '',
468
     *   'reply_markup'         => '',
469
     * ];
470
     * </code>
471
     *
472
     * @link https://core.telegram.org/bots/api#sendaudio
473
     *
474
     * @param array    $params
475
     *
476
     * @var int|string $params ['chat_id']
477
     * @var string     $params ['voice']
478
     * @var int        $params ['duration']
479
     * @var bool       $params ['disable_notification']
480
     * @var int        $params ['reply_to_message_id']
481
     * @var string     $params ['reply_markup']
482
     *
483
     * @return Message
484
     */
485 2
    public function sendVoice(array $params)
486
    {
487 2
        return $this->uploadFile('sendVoice', $params);
488
    }
489
490
    /**
491
     * Send point on the map.
492
     *
493
     * <code>
494
     * $params = [
495
     *   'chat_id'              => '',
496
     *   'latitude'             => '',
497
     *   'longitude'            => '',
498
     *   'disable_notification' => '',
499
     *   'reply_to_message_id'  => '',
500
     *   'reply_markup'         => '',
501
     * ];
502
     * </code>
503
     *
504
     * @link https://core.telegram.org/bots/api#sendlocation
505
     *
506
     * @param array    $params
507
     *
508
     * @var int|string $params ['chat_id']
509
     * @var float      $params ['latitude']
510
     * @var float      $params ['longitude']
511
     * @var bool       $params ['disable_notification']
512
     * @var int        $params ['reply_to_message_id']
513
     * @var string     $params ['reply_markup']
514
     *
515
     * @return Message
516
     */
517 2
    public function sendLocation(array $params)
518
    {
519 2
        $response = $this->post('sendLocation', $params);
520
521 2
        return new Message($response->getDecodedBody());
522
    }
523
524
    /**
525
     * Send information about a venue.
526
     *
527
     * <code>
528
     * $params = [
529
     *   'chat_id'              => '',
530
     *   'latitude'             => '',
531
     *   'longitude'            => '',
532
     *   'title'                => '',
533
     *   'address'              => '',
534
     *   'foursquare_id'        => '',
535
     *   'disable_notification' => '',
536
     *   'reply_to_message_id'  => '',
537
     *   'reply_markup'         => '',
538
     * ];
539
     * </code>
540
     *
541
     * @link https://core.telegram.org/bots/api#sendvenue
542
     *
543
     * @param array    $params
544
     *
545
     * @var int|string $params ['chat_id']
546
     * @var float      $params ['latitude']
547
     * @var float      $params ['longitude']
548
     * @var string     $params ['title']
549
     * @var string     $params ['address']
550
     * @var string     $params ['foursquare_id']
551
     * @var bool       $params ['disable_notification']
552
     * @var int        $params ['reply_to_message_id']
553
     * @var string     $params ['reply_markup']
554
     *
555
     * @return Message
556
     */
557
    public function sendVenue(array $params)
558
    {
559
        $response = $this->post('sendVenue', $params);
560
561
        return new Message($response->getDecodedBody());
562
    }
563
564
    /**
565
     * Send phone contacts.
566
     *
567
     * <code>
568
     * $params = [
569
     *   'chat_id'              => '',
570
     *   'phone_number'         => '',
571
     *   'first_name'           => '',
572
     *   'last_name'            => '',
573
     *   'disable_notification' => '',
574
     *   'reply_to_message_id'  => '',
575
     *   'reply_markup'         => '',
576
     * ];
577
     * </code>
578
     *
579
     * @link https://core.telegram.org/bots/api#sendcontact
580
     *
581
     * @param array    $params
582
     *
583
     * @var int|string $params ['chat_id']
584
     * @var string     $params ['phone_number']
585
     * @var string     $params ['first_name']
586
     * @var string     $params ['last_name']
587
     * @var bool       $params ['disable_notification']
588
     * @var int        $params ['reply_to_message_id']
589
     * @var string     $params ['reply_markup']
590
     *
591
     * @return Message
592
     */
593
    public function sendContact(array $params)
594
    {
595
        $response = $this->post('sendContact', $params);
596
597
        return new Message($response->getDecodedBody());
598
    }
599
600
    /**
601
     * Broadcast a Chat Action.
602
     *
603
     * <code>
604
     * $params = [
605
     *   'chat_id' => '',
606
     *   'action'  => '',
607
     * ];
608
     * </code>
609
     *
610
     * @link https://core.telegram.org/bots/api#sendchataction
611
     *
612
     * @param array    $params
613
     *
614
     * @var int|string $params ['chat_id']
615
     * @var string     $params ['action']
616
     *
617
     * @throws TelegramSDKException
618
     *
619
     * @return TelegramResponse
620
     */
621 4
    public function sendChatAction(array $params)
622
    {
623
        $validActions = [
624 4
            'typing',
625 4
            'upload_photo',
626 4
            'record_video',
627 4
            'upload_video',
628 4
            'record_audio',
629 4
            'upload_audio',
630 4
            'upload_document',
631 4
            'find_location',
632 4
        ];
633
634 4
        if (isset($params['action']) && in_array($params['action'], $validActions)) {
635 2
            return $this->post('sendChatAction', $params);
636
        }
637
638 2
        throw new TelegramSDKException('Invalid Action! Accepted value: '.implode(', ', $validActions));
639
    }
640
641
    /**
642
     * Returns a list of profile pictures for a user.
643
     *
644
     * <code>
645
     * $params = [
646
     *   'user_id' => '',
647
     *   'offset'  => '',
648
     *   'limit'   => '',
649
     * ];
650
     * </code>
651
     *
652
     * @link https://core.telegram.org/bots/api#getuserprofilephotos
653
     *
654
     * @param array $params
655
     *
656
     * @var int     $params ['user_id']
657
     * @var int     $params ['offset']
658
     * @var int     $params ['limit']
659
     *
660
     * @return UserProfilePhotos
661
     */
662
    public function getUserProfilePhotos(array $params)
663
    {
664
        $response = $this->post('getUserProfilePhotos', $params);
665
666
        return new UserProfilePhotos($response->getDecodedBody());
667
    }
668
669
    /**
670
     * Returns basic info about a file and prepare it for downloading.
671
     *
672
     * <code>
673
     * $params = [
674
     *   'file_id' => '',
675
     * ];
676
     * </code>
677
     *
678
     * The file can then be downloaded via the link
679
     * https://api.telegram.org/file/bot<token>/<file_path>,
680
     * where <file_path> is taken from the response.
681
     *
682
     * @link https://core.telegram.org/bots/api#getFile
683
     *
684
     * @param array $params
685
     *
686
     * @var string  $params ['file_id']
687
     *
688
     * @return File
689
     */
690 2
    public function getFile(array $params)
691
    {
692 2
        $response = $this->post('getFile', $params);
693
694 2
        return new File($response->getDecodedBody());
695
    }
696
697
    /**
698
     * Kick a user from a group or a supergroup.
699
     *
700
     * In the case of supergroups, the user will not be able to return to the group on their own using
701
     * invite links etc., unless unbanned first.
702
     *
703
     * The bot must be an administrator in the group for this to work.
704
     *
705
     * <code>
706
     * $params = [
707
     *   'chat_id'              => '',
708
     *   'user_id'              => '',
709
     * ];
710
     * </code>
711
     *
712
     * @link https://core.telegram.org/bots/api#kickchatmember
713
     *
714
     * @param array    $params
715
     *
716
     * @var int|string $params ['chat_id']
717
     * @var int        $params ['user_id']
718
     *
719
     * @return TelegramResponse
720
     */
721
    public function kickChatMember(array $params)
722
    {
723
        return $this->post('kickChatMember', $params);
724
    }
725
726
    /**
727
     * Unban a previously kicked user in a supergroup.
728
     *
729
     * The user will not return to the group automatically, but will be able to join via link, etc.
730
     *
731
     * The bot must be an administrator in the group for this to work.
732
     *
733
     * <code>
734
     * $params = [
735
     *   'chat_id'              => '',
736
     *   'user_id'              => '',
737
     * ];
738
     * </code>
739
     *
740
     * @link https://core.telegram.org/bots/api#unbanchatmember
741
     *
742
     * @param array    $params
743
     *
744
     * @var int|string $params ['chat_id']
745
     * @var int        $params ['user_id']
746
     *
747
     * @return TelegramResponse
748
     */
749
    public function unbanChatMember(array $params)
750
    {
751
        return $this->post('unbanChatMember', $params);
752
    }
753
754
    /**
755
     * Send answers to callback queries sent from inline keyboards.
756
     *
757
     * he answer will be displayed to the user as a notification at the top of the chat screen or as an alert.
758
     *
759
     * <code>
760
     * $params = [
761
     *   'callback_query_id'  => '',
762
     *   'text'               => '',
763
     *   'show_alert'         => '',
764
     * ];
765
     * </code>
766
     *
767
     * @link https://core.telegram.org/bots/api#answerCallbackQuery
768
     *
769
     * @param array $params
770
     *
771
     * @var string  $params ['callback_query_id']
772
     * @var string  $params ['text']
773
     * @var bool    $params ['show_alert']
774
     *
775
     * @return TelegramResponse
776
     */
777
    public function answerCallbackQuery(array $params)
778
    {
779
        return $this->post('answerCallbackQuery', $params);
780
    }
781
782
    /**
783
     * Edit text messages sent by the bot or via the bot (for inline bots).
784
     *
785
     * <code>
786
     * $params = [
787
     *   'chat_id'                  => '',
788
     *   'message_id'               => '',
789
     *   'inline_message_id'        => '',
790
     *   'text'                     => '',
791
     *   'parse_mode'               => '',
792
     *   'disable_web_page_preview' => '',
793
     *   'reply_markup'             => '',
794
     * ];
795
     * </code>
796
     *
797
     * @link https://core.telegram.org/bots/api#editMessageText
798
     *
799
     * @param array    $params
800
     *
801
     * @var int|string $params ['chat_id']
802
     * @var int        $params ['message_id']
803
     * @var string     $params ['inline_message_id']
804
     * @var string     $params ['text']
805
     * @var string     $params ['parse_mode']
806
     * @var bool       $params ['disable_web_page_preview']
807
     * @var string     $params ['reply_markup']
808
     *
809
     * @return TelegramResponse
810
     */
811
    public function editMessageText(array $params)
812
    {
813
        $response = $this->post('editMessageText', $params);
814
815
        return new Message($response->getDecodedBody());
816
    }
817
818
    /**
819
     * Edit captions of messages sent by the bot or via the bot (for inline bots).
820
     *
821
     * <code>
822
     * $params = [
823
     *   'chat_id'                  => '',
824
     *   'message_id'               => '',
825
     *   'inline_message_id'        => '',
826
     *   'caption'                  => '',
827
     *   'reply_markup'             => '',
828
     * ];
829
     * </code>
830
     *
831
     * @link https://core.telegram.org/bots/api#editMessageCaption
832
     *
833
     * @param array    $params
834
     *
835
     * @var int|string $params ['chat_id']
836
     * @var int        $params ['message_id']
837
     * @var string     $params ['inline_message_id']
838
     * @var string     $params ['caption']
839
     * @var string     $params ['reply_markup']
840
     *
841
     * @return TelegramResponse
842
     */
843
    public function editMessageCaption(array $params)
844
    {
845
        $response = $this->post('editMessageCaption', $params);
846
847
        return new Message($response->getDecodedBody());
848
    }
849
850
    /**
851
     * Edit only the reply markup of messages sent by the bot or via the bot (for inline bots).
852
     *
853
     * <code>
854
     * $params = [
855
     *   'chat_id'                  => '',
856
     *   'message_id'               => '',
857
     *   'inline_message_id'        => '',
858
     *   'reply_markup'             => '',
859
     * ];
860
     * </code>
861
     *
862
     * @link https://core.telegram.org/bots/api#editMessageReplyMarkup
863
     *
864
     * @param array    $params
865
     *
866
     * @var int|string $params ['chat_id']
867
     * @var int        $params ['message_id']
868
     * @var string     $params ['inline_message_id']
869
     * @var string     $params ['reply_markup']
870
     *
871
     * @return TelegramResponse
872
     */
873
    public function editMessageReplyMarkup(array $params)
874
    {
875
        $response = $this->post('editMessageReplyMarkup', $params);
876
877
        return new Message($response->getDecodedBody());
878
    }
879
880
    /**
881
     * Use this method to send answers to an inline query.
882
     *
883
     * <code>
884
     * $params = [
885
     *   'inline_query_id'      => '',
886
     *   'results'              => [],
887
     *   'cache_time'           => 0,
888
     *   'is_personal'          => false,
889
     *   'next_offset'          => '',
890
     *   'switch_pm_text'       => '',
891
     *   'switch_pm_parameter'  => '',
892
     * ];
893
     * </code>
894
     *
895
     * @link https://core.telegram.org/bots/api#answerinlinequery
896
     *
897
     * @param array     $params
898
     *
899
     * @var string      $params ['inline_query_id']
900
     * @var array       $params ['results']
901
     * @var int|null    $params ['cache_time']
902
     * @var bool|null   $params ['is_personal']
903
     * @var string|null $params ['next_offset']
904
     * @var string|null $params ['switch_pm_text']
905
     * @var string|null $params ['switch_pm_parameter']
906
     *
907
     * @return bool
908
     */
909
    public function answerInlineQuery(array $params = [])
910
    {
911
        if (is_array($params['results'])) {
912
            $params['results'] = json_encode($params['results']);
913
        }
914
915
        return $this->post('answerInlineQuery', $params);
916
    }
917
918
    /**
919
     * Set a Webhook to receive incoming updates via an outgoing webhook.
920
     *
921
     * <code>
922
     * $params = [
923
     *   'url'         => '',
924
     *   'certificate' => '',
925
     * ];
926
     * </code>
927
     *
928
     * @link https://core.telegram.org/bots/api#setwebhook
929
     *
930
     * @param array $params
931
     *
932
     * @var string  $params ['url']         HTTPS url to send updates to.
933
     * @var string  $params ['certificate'] Upload your public key certificate so that the root certificate in
934
     *                                      use can be checked.
935
     *
936
     * @throws TelegramSDKException
937
     *
938
     * @return TelegramResponse
939
     */
940 6
    public function setWebhook(array $params)
941
    {
942 6
        if (filter_var($params['url'], FILTER_VALIDATE_URL) === false) {
943 2
            throw new TelegramSDKException('Invalid URL Provided');
944
        }
945
946 4
        if (parse_url($params['url'], PHP_URL_SCHEME) !== 'https') {
947 2
            throw new TelegramSDKException('Invalid URL, should be a HTTPS url.');
948
        }
949
950 2
        return $this->uploadFile('setWebhook', $params);
951
    }
952
953
    /**
954
     * Returns webhook updates sent by Telegram.
955
     * Works only if you set a webhook.
956
     *
957
     * @see setWebhook
958
     *
959
     * @return Update
960
     */
961
    public function getWebhookUpdates()
962
    {
963
        $body = json_decode(file_get_contents('php://input'), true);
964
965
        return new Update($body);
966
    }
967
968
    /**
969
     * Removes the outgoing webhook (if any).
970
     *
971
     * @return TelegramResponse
972
     */
973 2
    public function removeWebhook()
974
    {
975 2
        $url = '';
976
977 2
        return $this->post('setWebhook', compact('url'));
978
    }
979
980
    /**
981
     * Use this method to receive incoming updates using long polling.
982
     *
983
     * <code>
984
     * $params = [
985
     *   'offset'  => '',
986
     *   'limit'   => '',
987
     *   'timeout' => '',
988
     * ];
989
     * </code>
990
     *
991
     * @link https://core.telegram.org/bots/api#getupdates
992
     *
993
     * @param array  $params
994
     *
995
     * @var int|null $params ['offset']
996
     * @var int|null $params ['limit']
997
     * @var int|null $params ['timeout']
998
     *
999
     * @return Update[]
1000
     */
1001 6
    public function getUpdates(array $params = [])
1002
    {
1003 6
        $response = $this->post('getUpdates', $params);
1004 6
        $updates = $response->getDecodedBody();
1005
1006 6
        $data = [];
1007 6
        if (isset($updates['result'])) {
1008 6
            foreach ($updates['result'] as $update) {
1009 6
                $data[] = new Update($update);
1010 6
            }
1011 6
        }
1012
1013 6
        return $data;
1014
    }
1015
1016
1017
    /**
1018
     * Builds a custom keyboard markup.
1019
     *
1020
     * <code>
1021
     * $params = [
1022
     *   'keyboard'          => '',
1023
     *   'resize_keyboard'   => '',
1024
     *   'one_time_keyboard' => '',
1025
     *   'selective'         => '',
1026
     * ];
1027
     * </code>
1028
     *
1029
     * @deprecated Use Telegram\Bot\Keyboard\Keyboard::make(array $params = []) instead.
1030
     *             To be removed in next major version.
1031
     *
1032
     * @link       https://core.telegram.org/bots/api#replykeyboardmarkup
1033
     *
1034
     * @param array $params
1035
     *
1036
     * @var array   $params ['keyboard']
1037
     * @var bool    $params ['resize_keyboard']
1038
     * @var bool    $params ['one_time_keyboard']
1039
     * @var bool    $params ['selective']
1040
     *
1041
     * @return string
1042
     */
1043
    public function replyKeyboardMarkup(array $params)
1044
    {
1045
        return Keyboard::make($params);
1046
    }
1047
1048
    /**
1049
     * Hide the current custom keyboard and display the default letter-keyboard.
1050
     *
1051
     * <code>
1052
     * $params = [
1053
     *   'hide_keyboard' => true,
1054
     *   'selective'     => false,
1055
     * ];
1056
     * </code>
1057
     *
1058
     * @deprecated Use Telegram\Bot\Keyboard\Keyboard::hide(array $params = []) instead.
1059
     *             To be removed in next major version.
1060
     *
1061
     * @link       https://core.telegram.org/bots/api#replykeyboardhide
1062
     *
1063
     * @param array $params
1064
     *
1065
     * @var bool    $params ['hide_keyboard']
1066
     * @var bool    $params ['selective']
1067
     *
1068
     * @return string
1069
     */
1070
    public static function replyKeyboardHide(array $params = [])
1071
    {
1072
        return Keyboard::hide($params);
1073
    }
1074
1075
    /**
1076
     * Display a reply interface to the user (act as if the user has selected the bot‘s message and tapped ’Reply').
1077
     *
1078
     * <code>
1079
     * $params = [
1080
     *   'force_reply' => true,
1081
     *   'selective'   => false,
1082
     * ];
1083
     * </code>
1084
     *
1085
     * @deprecated Use Telegram\Bot\Keyboard\Keyboard::forceReply(array $params = []) instead.
1086
     *             To be removed in next major version.
1087
     *
1088
     * @link       https://core.telegram.org/bots/api#forcereply
1089
     *
1090
     * @param array $params
1091
     *
1092
     * @var bool    $params ['force_reply']
1093
     * @var bool    $params ['selective']
1094
     *
1095
     * @return string
1096
     */
1097
    public static function forceReply(array $params = [])
1098
    {
1099
        return Keyboard::forceReply($params);
1100
    }
1101
1102
    /**
1103
     * Processes Inbound Commands.
1104
     *
1105
     * @param bool $webhook
1106
     *
1107
     * @return Update|Update[]
1108
     */
1109 6
    public function commandsHandler($webhook = false)
1110
    {
1111 6
        if ($webhook) {
1112
            $update = $this->getWebhookUpdates();
1113
            $this->processCommand($update);
1114
1115
            return $update;
1116
        }
1117
1118 6
        $updates = $this->getUpdates();
1119 6
        $highestId = -1;
1120
1121 6
        foreach ($updates as $update) {
1122 6
            $highestId = $update->getUpdateId();
1123 6
            $this->processCommand($update);
1124 6
        }
1125
1126
        //An update is considered confirmed as soon as getUpdates is called with an offset higher than its update_id.
1127 6
        if ($highestId != -1) {
1128 6
            $params = [];
1129 6
            $params['offset'] = $highestId + 1;
1130 6
            $params['limit'] = 1;
1131 6
            $this->getUpdates($params);
1132 6
        }
1133
1134 6
        return $updates;
1135
    }
1136
1137
    /**
1138
     * Check update object for a command and process.
1139
     *
1140
     * @param Update $update
1141
     */
1142 6
    public function processCommand(Update $update)
1143
    {
1144 6
        $message = $update->getMessage();
1145
1146 6
        if ($message !== null && $message->has('text')) {
1147 6
            $this->getCommandBus()->handler($message->getText(), $update);
1148 6
        }
1149 6
    }
1150
1151
    /**
1152
     * Helper to Trigger Commands.
1153
     *
1154
     * @param string $name   Command Name
1155
     * @param Update $update Update Object
1156
     *
1157
     * @return mixed
1158
     */
1159
    public function triggerCommand($name, Update $update)
1160
    {
1161
        return $this->getCommandBus()->execute($name, $update->getMessage()->getText(), $update);
1162
    }
1163
1164
    /**
1165
     * Determine if a given type is the message.
1166
     *
1167
     * @param string         $type
1168
     * @param Update|Message $object
1169
     *
1170
     * @return bool
1171
     */
1172
    public function isMessageType($type, $object)
1173
    {
1174
        if ($object instanceof Update) {
1175
            $object = $object->getMessage();
1176
        }
1177
1178
        if ($object->has(strtolower($type))) {
1179
            return true;
1180
        }
1181
1182
        return $this->detectMessageType($object) === $type;
1183
    }
1184
1185
    /**
1186
     * Detect Message Type Based on Update or Message Object.
1187
     *
1188
     * @param Update|Message $object
1189
     *
1190
     * @return string|null
1191
     */
1192
    public function detectMessageType($object)
1193
    {
1194
        if ($object instanceof Update) {
1195
            $object = $object->getMessage();
1196
        }
1197
1198
        $types = [
1199
            'text',
1200
            'audio',
1201
            'document',
1202
            'photo',
1203
            'sticker',
1204
            'video',
1205
            'voice',
1206
            'contact',
1207
            'location',
1208
            'venue',
1209
            'new_chat_member',
1210
            'left_chat_member',
1211
            'new_chat_title',
1212
            'new_chat_photo',
1213
            'delete_chat_photo',
1214
            'group_chat_created',
1215
            'supergroup_chat_created',
1216
            'channel_chat_created',
1217
            'migrate_to_chat_id',
1218
            'migrate_from_chat_id',
1219
            'pinned_message',
1220
        ];
1221
1222
        return $object->keys()
1223
            ->intersect($types)
1224
            ->pop();
1225
    }
1226
1227
    /**
1228
     * Sends a GET request to Telegram Bot API and returns the result.
1229
     *
1230
     * @param string $endpoint
1231
     * @param array  $params
1232
     *
1233
     * @throws TelegramSDKException
1234
     *
1235
     * @return TelegramResponse
1236
     */
1237
    protected function get($endpoint, $params = [])
1238
    {
1239
        if (array_key_exists('reply_markup', $params)) {
1240
            $params['reply_markup'] = (string)$params['reply_markup'];
1241
        }
1242
1243
        return $this->sendRequest(
1244
            'GET',
1245
            $endpoint,
1246
            $params
1247
        );
1248
    }
1249
1250
    /**
1251
     * Sends a POST request to Telegram Bot API and returns the result.
1252
     *
1253
     * @param string $endpoint
1254
     * @param array  $params
1255
     * @param bool   $fileUpload Set true if a file is being uploaded.
1256
     *
1257
     * @return TelegramResponse
1258
     */
1259 40
    protected function post($endpoint, array $params = [], $fileUpload = false)
1260
    {
1261 40
        if ($fileUpload) {
1262 16
            $params = ['multipart' => $params];
1263 16
        } else {
1264
1265 24
            if (array_key_exists('reply_markup', $params)) {
1266
                $params['reply_markup'] = (string)$params['reply_markup'];
1267
            }
1268
1269 24
            $params = ['form_params' => $params];
1270
        }
1271
1272 40
        return $this->sendRequest(
1273 40
            'POST',
1274 40
            $endpoint,
1275
            $params
1276 40
        );
1277
    }
1278
1279
    /**
1280
     * Sends a multipart/form-data request to Telegram Bot API and returns the result.
1281
     * Used primarily for file uploads.
1282
     *
1283
     * @param string $endpoint
1284
     * @param array  $params
1285
     *
1286
     * @throws TelegramSDKException
1287
     *
1288
     * @return Message
1289
     */
1290 16
    protected function uploadFile($endpoint, array $params = [])
1291
    {
1292 16
        $i = 0;
1293 16
        $multipart_params = [];
1294 16
        foreach ($params as $name => $contents) {
1295 16
            if (is_null($contents)) {
1296
                continue;
1297
            }
1298
1299 16
            if (!is_resource($contents) && $name !== 'url') {
1300 14
                $validUrl = filter_var($contents, FILTER_VALIDATE_URL);
1301 14
                $contents = (is_file($contents) || $validUrl) ? (new InputFile($contents))->open() : (string)$contents;
1302 14
            }
1303
1304 16
            $multipart_params[$i]['name'] = $name;
1305 16
            $multipart_params[$i]['contents'] = $contents;
1306 16
            ++$i;
1307 16
        }
1308
1309 16
        $response = $this->post($endpoint, $multipart_params, true);
1310
1311 16
        return new Message($response->getDecodedBody());
1312
    }
1313
1314
    /**
1315
     * Sends a request to Telegram Bot API and returns the result.
1316
     *
1317
     * @param string $method
1318
     * @param string $endpoint
1319
     * @param array  $params
1320
     *
1321
     * @throws TelegramSDKException
1322
     *
1323
     * @return TelegramResponse
1324
     */
1325 40
    protected function sendRequest(
1326
        $method,
1327
        $endpoint,
1328
        array $params = []
1329
    ) {
1330 40
        $request = $this->request($method, $endpoint, $params);
1331
1332 40
        return $this->lastResponse = $this->client->sendRequest($request);
1333
    }
1334
1335
    /**
1336
     * Instantiates a new TelegramRequest entity.
1337
     *
1338
     * @param string $method
1339
     * @param string $endpoint
1340
     * @param array  $params
1341
     *
1342
     * @return TelegramRequest
1343
     */
1344 40
    protected function request(
1345
        $method,
1346
        $endpoint,
1347
        array $params = []
1348
    ) {
1349 40
        return new TelegramRequest(
1350 40
            $this->getAccessToken(),
1351 40
            $method,
1352 40
            $endpoint,
1353 40
            $params,
1354 40
            $this->isAsyncRequest(),
1355 40
            $this->getTimeOut(),
1356 40
            $this->getConnectTimeOut()
1357 40
        );
1358
    }
1359
1360
    /**
1361
     * Magic method to process any "get" requests.
1362
     *
1363
     * @param $method
1364
     * @param $arguments
1365
     *
1366
     * @return bool|TelegramResponse|UnknownObject
1367
     */
1368 2
    public function __call($method, $arguments)
1369
    {
1370 2
        if (preg_match('/^\w+Commands?/', $method, $matches)) {
1371 2
            return call_user_func_array([$this->getCommandBus(), $matches[0]], $arguments);
1372
        }
1373
1374
        $action = substr($method, 0, 3);
1375
        if ($action === 'get') {
1376
            /* @noinspection PhpUndefinedFunctionInspection */
1377
            $class_name = studly_case(substr($method, 3));
1378
            $class = 'Telegram\Bot\Objects\\'.$class_name;
1379
            $response = $this->post($method, $arguments[0] ?: []);
1380
1381
            if (class_exists($class)) {
1382
                return new $class($response->getDecodedBody());
1383
            }
1384
1385
            return $response;
1386
        }
1387
        $response = $this->post($method, $arguments[0]);
1388
1389
        return new UnknownObject($response->getDecodedBody());
1390
    }
1391
1392
    /**
1393
     * Set the IoC Container.
1394
     *
1395
     * @param $container Container instance
1396
     *
1397
     * @return void
1398
     */
1399 2
    public static function setContainer(Container $container)
1400
    {
1401 2
        self::$container = $container;
1402 2
    }
1403
1404
    /**
1405
     * Get the IoC Container.
1406
     *
1407
     * @return Container
1408
     */
1409 2
    public function getContainer()
1410
    {
1411 2
        return self::$container;
1412
    }
1413
1414
    /**
1415
     * Check if IoC Container has been set.
1416
     *
1417
     * @return boolean
1418
     */
1419
    public function hasContainer()
1420
    {
1421
        return self::$container !== null;
1422
    }
1423
1424
    /**
1425
     * @return int
1426
     */
1427 40
    public function getTimeOut()
1428
    {
1429 40
        return $this->timeOut;
1430
    }
1431
1432
    /**
1433
     * @param int $timeOut
1434
     *
1435
     * @return $this
1436
     */
1437 2
    public function setTimeOut($timeOut)
1438
    {
1439 2
        $this->timeOut = $timeOut;
1440
1441 2
        return $this;
1442
    }
1443
1444
    /**
1445
     * @return int
1446
     */
1447 40
    public function getConnectTimeOut()
1448
    {
1449 40
        return $this->connectTimeOut;
1450
    }
1451
1452
    /**
1453
     * @param int $connectTimeOut
1454
     *
1455
     * @return $this
1456
     */
1457 2
    public function setConnectTimeOut($connectTimeOut)
1458
    {
1459 2
        $this->connectTimeOut = $connectTimeOut;
1460
1461 2
        return $this;
1462
    }
1463
}
1464