Completed
Push — master ( d21bd9...06a30b )
by Irfaq
02:47
created

Api::removeCommands()   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 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 2
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\Update;
14
use Telegram\Bot\Objects\User;
15
use Telegram\Bot\Objects\UserProfilePhotos;
16
17
/**
18
 * Class Api.
19
 *
20
 * @mixin Commands\CommandBus
21
 */
22
class Api
23
{
24
    /**
25
     * @var string Version number of the Telegram Bot PHP SDK.
26
     */
27
    const VERSION = '3.0.0';
28
29
    /**
30
     * @var string The name of the environment variable that contains the Telegram Bot API Access Token.
31
     */
32
    const BOT_TOKEN_ENV_NAME = 'TELEGRAM_BOT_TOKEN';
33
34
    /**
35
     * @var TelegramClient The Telegram client service.
36
     */
37
    protected $client;
38
39
    /**
40
     * @var string Telegram Bot API Access Token.
41
     */
42
    protected $accessToken = null;
43
44
    /**
45
     * @var TelegramResponse|null Stores the last request made to Telegram Bot API.
46
     */
47
    protected $lastResponse;
48
49
    /**
50
     * @var bool Indicates if the request to Telegram will be asynchronous (non-blocking).
51
     */
52
    protected $isAsyncRequest = false;
53
54
    /**
55
     * @var CommandBus|null Telegram Command Bus.
56
     */
57
    protected $commandBus = null;
58
59
    /**
60
     * @var Container IoC Container
61
     */
62
    protected static $container = null;
63
64
    /**
65
     * Timeout of the request in seconds.
66
     *
67
     * @var int
68
     */
69
    protected $timeOut = 60;
70
71
    /**
72
     * Connection timeout of the request in seconds.
73
     *
74
     * @var int
75
     */
76
    protected $connectTimeOut = 10;
77
78
    /**
79
     * Instantiates a new Telegram super-class object.
80
     *
81
     *
82
     * @param string                     $token               The Telegram Bot API Access Token.
83
     * @param bool                       $async               (Optional) Indicates if the request to Telegram
84
     *                                                        will be asynchronous (non-blocking).
85
     * @param string|HttpClientInterface $http_client_handler (Optional) Custom HTTP Client Handler.
86
     *
87
     * @throws TelegramSDKException
88
     */
89 76
    public function __construct($token = null, $async = false, $http_client_handler = null)
90
    {
91 76
        $this->accessToken = isset($token) ? $token : getenv(static::BOT_TOKEN_ENV_NAME);
92 76
        if (!$this->accessToken) {
93 2
            throw new TelegramSDKException('Required "token" not supplied in config and could not find fallback environment variable "'.static::BOT_TOKEN_ENV_NAME.'"');
94
        }
95
96 76
        $httpClientHandler = null;
97 76
        if (isset($http_client_handler)) {
98 46
            if ($http_client_handler instanceof HttpClientInterface) {
99 42
                $httpClientHandler = $http_client_handler;
100 46
            } elseif ($http_client_handler === 'guzzle') {
101 2
                $httpClientHandler = new GuzzleHttpClient();
102 2
            } else {
103 2
                throw new \InvalidArgumentException('The HTTP Client Handler must be set to "guzzle", or be an instance of Telegram\Bot\HttpClients\HttpClientInterface');
104
            }
105 44
        }
106
107 76
        if (isset($async)) {
108 76
            $this->setAsyncRequest($async);
109 76
        }
110
111 76
        $this->client = new TelegramClient($httpClientHandler);
112 76
        $this->commandBus = new CommandBus($this);
113 76
    }
114
115
    /**
116
     * Returns the TelegramClient service.
117
     *
118
     * @return TelegramClient
119
     */
120 6
    public function getClient()
121
    {
122 6
        return $this->client;
123
    }
124
125
    /**
126
     * Returns Telegram Bot API Access Token.
127
     *
128
     * @return string
129
     */
130 42
    public function getAccessToken()
131
    {
132 42
        return $this->accessToken;
133
    }
134
135
    /**
136
     * Returns the last response returned from API request.
137
     *
138
     * @return TelegramResponse
139
     */
140 2
    public function getLastResponse()
141
    {
142 2
        return $this->lastResponse;
143
    }
144
145
    /**
146
     * Sets the bot access token to use with API requests.
147
     *
148
     * @param string $accessToken The bot access token to save.
149
     *
150
     * @throws \InvalidArgumentException
151
     *
152
     * @return Api
153
     */
154 8
    public function setAccessToken($accessToken)
155
    {
156 8
        if (is_string($accessToken)) {
157 2
            $this->accessToken = $accessToken;
158
159 2
            return $this;
160
        }
161
162 6
        throw new \InvalidArgumentException('The Telegram bot access token must be of type "string"');
163
    }
164
165
    /**
166
     * Make this request asynchronous (non-blocking).
167
     *
168
     * @param bool $isAsyncRequest
169
     *
170
     * @return Api
171
     */
172 76
    public function setAsyncRequest($isAsyncRequest)
173
    {
174 76
        $this->isAsyncRequest = $isAsyncRequest;
175
176 76
        return $this;
177
    }
178
179
    /**
180
     * Check if this is an asynchronous request (non-blocking).
181
     *
182
     * @return bool
183
     */
184 42
    public function isAsyncRequest()
185
    {
186 42
        return $this->isAsyncRequest;
187
    }
188
189
    /**
190
     * Returns SDK's Command Bus.
191
     *
192
     * @return CommandBus
193
     */
194 8
    public function getCommandBus()
195
    {
196 8
        return $this->commandBus;
197
    }
198
199
    /**
200
     * A simple method for testing your bot's auth token.
201
     * Returns basic information about the bot in form of a User object.
202
     *
203
     * @link https://core.telegram.org/bots/api#getme
204
     *
205
     * @return User
206
     */
207 4
    public function getMe()
208
    {
209 4
        $response = $this->post('getMe');
210
211 2
        return new User($response->getDecodedBody());
212
    }
213
214
    /**
215
     * Send text messages.
216
     *
217
     * <code>
218
     * $params = [
219
     *   'chat_id'                  => '',
220
     *   'text'                     => '',
221
     *   'parse_mode'               => '',
222
     *   'disable_web_page_preview' => '',
223
     *   'reply_to_message_id'      => '',
224
     *   'reply_markup'             => '',
225
     * ];
226
     * </code>
227
     *
228
     * @link https://core.telegram.org/bots/api#sendmessage
229
     *
230
     * @param array    $params
231
     *
232
     * @var int|string $params ['chat_id']
233
     * @var string     $params ['text']
234
     * @var string     $params ['parse_mode']
235
     * @var bool       $params ['disable_web_page_preview']
236
     * @var int        $params ['reply_to_message_id']
237
     * @var string     $params ['reply_markup']
238
     *
239
     * @return Message
240
     */
241 4
    public function sendMessage(array $params)
242
    {
243 4
        $response = $this->post('sendMessage', $params);
244
245 4
        return new Message($response->getDecodedBody());
246
    }
247
248
    /**
249
     * Forward messages of any kind.
250
     *
251
     * <code>
252
     * $params = [
253
     *   'chat_id'      => '',
254
     *   'from_chat_id' => '',
255
     *   'message_id'   => '',
256
     * ];
257
     * </code>
258
     *
259
     * @link https://core.telegram.org/bots/api#forwardmessage
260
     *
261
     * @param array    $params
262
     *
263
     * @var int|string $params ['chat_id']
264
     * @var int        $params ['from_chat_id']
265
     * @var int        $params ['message_id']
266
     *
267
     * @return Message
268
     */
269 2
    public function forwardMessage(array $params)
270
    {
271 2
        $response = $this->post('forwardMessage', $params);
272
273 2
        return new Message($response->getDecodedBody());
274
    }
275
276
    /**
277
     * Send Photos.
278
     *
279
     * <code>
280
     * $params = [
281
     *   'chat_id'             => '',
282
     *   'photo'               => '',
283
     *   'caption'             => '',
284
     *   'reply_to_message_id' => '',
285
     *   'reply_markup'        => '',
286
     * ];
287
     * </code>
288
     *
289
     * @link https://core.telegram.org/bots/api#sendphoto
290
     *
291
     * @param array    $params
292
     *
293
     * @var int|string $params ['chat_id']
294
     * @var string     $params ['photo']
295
     * @var string     $params ['caption']
296
     * @var int        $params ['reply_to_message_id']
297
     * @var string     $params ['reply_markup']
298
     *
299
     * @return Message
300
     */
301 4
    public function sendPhoto(array $params)
302
    {
303 4
        return $this->uploadFile('sendPhoto', $params);
304
    }
305
306
    /**
307
     * Send regular audio files.
308
     *
309
     * <code>
310
     * $params = [
311
     *   'chat_id'             => '',
312
     *   'audio'               => '',
313
     *   'duration'            => '',
314
     *   'performer'           => '',
315
     *   'title'               => '',
316
     *   'reply_to_message_id' => '',
317
     *   'reply_markup'        => '',
318
     * ];
319
     * </code>
320
     *
321
     * @link https://core.telegram.org/bots/api#sendaudio
322
     *
323
     * @param array    $params
324
     *
325
     * @var int|string $params ['chat_id']
326
     * @var string     $params ['audio']
327
     * @var int        $params ['duration']
328
     * @var string     $params ['performer']
329
     * @var string     $params ['title']
330
     * @var int        $params ['reply_to_message_id']
331
     * @var string     $params ['reply_markup']
332
     *
333
     * @return Message
334
     */
335 2
    public function sendAudio(array $params)
336
    {
337 2
        return $this->uploadFile('sendAudio', $params);
338
    }
339
340
    /**
341
     * Send general files.
342
     *
343
     * <code>
344
     * $params = [
345
     *   'chat_id'             => '',
346
     *   'document'            => '',
347
     *   'reply_to_message_id' => '',
348
     *   'reply_markup'        => '',
349
     * ];
350
     * </code>
351
     *
352
     * @link https://core.telegram.org/bots/api#senddocument
353
     *
354
     * @param array    $params
355
     *
356
     * @var int|string $params ['chat_id']
357
     * @var string     $params ['document']
358
     * @var int        $params ['reply_to_message_id']
359
     * @var string     $params ['reply_markup']
360
     *
361
     * @return Message
362
     */
363 2
    public function sendDocument(array $params)
364
    {
365 2
        return $this->uploadFile('sendDocument', $params);
366
    }
367
368
    /**
369
     * Send .webp stickers.
370
     *
371
     * <code>
372
     * $params = [
373
     *   'chat_id' => '',
374
     *   'sticker' => '',
375
     *   'reply_to_message_id' => '',
376
     *   'reply_markup' => '',
377
     * ];
378
     * </code>
379
     *
380
     * @link https://core.telegram.org/bots/api#sendsticker
381
     *
382
     * @param array    $params
383
     *
384
     * @var int|string $params ['chat_id']
385
     * @var string     $params ['sticker']
386
     * @var int        $params ['reply_to_message_id']
387
     * @var string     $params ['reply_markup']
388
     *
389
     * @throws TelegramSDKException
390
     *
391
     * @return Message
392
     */
393 2
    public function sendSticker(array $params)
394
    {
395 2
        if (is_file($params['sticker']) && (pathinfo($params['sticker'], PATHINFO_EXTENSION) !== 'webp')) {
396
            throw new TelegramSDKException('Invalid Sticker Provided. Supported Format: Webp');
397
        }
398
399 2
        return $this->uploadFile('sendSticker', $params);
400
    }
401
402
    /**
403
     * Send Video File, Telegram clients support mp4 videos (other formats may be sent as Document).
404
     *
405
     * <code>
406
     * $params = [
407
     *   'chat_id'             => '',
408
     *   'video'               => '',
409
     *   'duration'            => '',
410
     *   'caption'             => '',
411
     *   'reply_to_message_id' => '',
412
     *   'reply_markup'        => '',
413
     * ];
414
     * </code>
415
     *
416
     * @see  sendDocument
417
     * @link https://core.telegram.org/bots/api#sendvideo
418
     *
419
     * @param array    $params
420
     *
421
     * @var int|string $params ['chat_id']
422
     * @var string     $params ['video']
423
     * @var int        $params ['duration']
424
     * @var string     $params ['caption']
425
     * @var int        $params ['reply_to_message_id']
426
     * @var string     $params ['reply_markup']
427
     *
428
     * @return Message
429
     */
430 2
    public function sendVideo(array $params)
431
    {
432 2
        return $this->uploadFile('sendVideo', $params);
433
    }
434
435
    /**
436
     * Send voice audio files.
437
     *
438
     * <code>
439
     * $params = [
440
     *   'chat_id'             => '',
441
     *   'voice'               => '',
442
     *   'duration'            => '',
443
     *   'reply_to_message_id' => '',
444
     *   'reply_markup'        => '',
445
     * ];
446
     * </code>
447
     *
448
     * @link https://core.telegram.org/bots/api#sendaudio
449
     *
450
     * @param array    $params
451
     *
452
     * @var int|string $params ['chat_id']
453
     * @var string     $params ['voice']
454
     * @var int        $params ['duration']
455
     * @var int        $params ['reply_to_message_id']
456
     * @var string     $params ['reply_markup']
457
     *
458
     * @return Message
459
     */
460 2
    public function sendVoice(array $params)
461
    {
462 2
        return $this->uploadFile('sendVoice', $params);
463
    }
464
465
    /**
466
     * Send point on the map.
467
     *
468
     * <code>
469
     * $params = [
470
     *   'chat_id'             => '',
471
     *   'latitude'            => '',
472
     *   'longitude'           => '',
473
     *   'reply_to_message_id' => '',
474
     *   'reply_markup'        => '',
475
     * ];
476
     * </code>
477
     *
478
     * @link https://core.telegram.org/bots/api#sendlocation
479
     *
480
     * @param array    $params
481
     *
482
     * @var int|string $params ['chat_id']
483
     * @var float      $params ['latitude']
484
     * @var float      $params ['longitude']
485
     * @var int        $params ['reply_to_message_id']
486
     * @var string     $params ['reply_markup']
487
     *
488
     * @return Message
489
     */
490 2
    public function sendLocation(array $params)
491
    {
492 2
        $response = $this->post('sendLocation', $params);
493
494 2
        return new Message($response->getDecodedBody());
495
    }
496
497
    /**
498
     * Broadcast a Chat Action.
499
     *
500
     * <code>
501
     * $params = [
502
     *   'chat_id' => '',
503
     *   'action'  => '',
504
     * ];
505
     * </code>
506
     *
507
     * @link https://core.telegram.org/bots/api#sendchataction
508
     *
509
     * @param array    $params
510
     *
511
     * @var int|string $params ['chat_id']
512
     * @var string     $params ['action']
513
     *
514
     * @throws TelegramSDKException
515
     *
516
     * @return TelegramResponse
517
     */
518 4
    public function sendChatAction(array $params)
519
    {
520
        $validActions = [
521 4
            'typing',
522 4
            'upload_photo',
523 4
            'record_video',
524 4
            'upload_video',
525 4
            'record_audio',
526 4
            'upload_audio',
527 4
            'upload_document',
528 4
            'find_location',
529 4
        ];
530
531 4
        if (isset($params['action']) && in_array($params['action'], $validActions)) {
532 2
            return $this->post('sendChatAction', $params);
533
        }
534
535 2
        throw new TelegramSDKException('Invalid Action! Accepted value: '.implode(', ', $validActions));
536
    }
537
538
    /**
539
     * Returns a list of profile pictures for a user.
540
     *
541
     * <code>
542
     * $params = [
543
     *   'user_id' => '',
544
     *   'offset'  => '',
545
     *   'limit'   => '',
546
     * ];
547
     * </code>
548
     *
549
     * @link https://core.telegram.org/bots/api#getuserprofilephotos
550
     *
551
     * @param array $params
552
     *
553
     * @var int     $params ['user_id']
554
     * @var int     $params ['offset']
555
     * @var int     $params ['limit']
556
     *
557
     * @return UserProfilePhotos
558
     */
559
    public function getUserProfilePhotos(array $params)
560
    {
561
        $response = $this->post('getUserProfilePhotos', $params);
562
563
        return new UserProfilePhotos($response->getDecodedBody());
564
    }
565
566
    /**
567
     * Returns basic info about a file and prepare it for downloading.
568
     *
569
     * <code>
570
     * $params = [
571
     *   'file_id' => '',
572
     * ];
573
     * </code>
574
     *
575
     * The file can then be downloaded via the link
576
     * https://api.telegram.org/file/bot<token>/<file_path>,
577
     * where <file_path> is taken from the response.
578
     *
579
     * @link https://core.telegram.org/bots/api#getFile
580
     *
581
     * @param array $params
582
     *
583
     * @var string  $params ['file_id']
584
     *
585
     * @return File
586
     */
587 2
    public function getFile(array $params)
588
    {
589 2
        $response = $this->post('getFile', $params);
590
591 2
        return new File($response->getDecodedBody());
592
    }
593
594
    /**
595
     * Set a Webhook to receive incoming updates via an outgoing webhook.
596
     *
597
     * <code>
598
     * $params = [
599
     *   'url'         => '',
600
     *   'certificate' => '',
601
     * ];
602
     * </code>
603
     *
604
     * @link https://core.telegram.org/bots/api#setwebhook
605
     *
606
     * @param array $params
607
     *
608
     * @var string  $params ['url']         HTTPS url to send updates to.
609
     * @var string  $params ['certificate'] Upload your public key certificate so that the root certificate in
610
     *                                      use can be checked.
611
     *
612
     * @throws TelegramSDKException
613
     *
614
     * @return TelegramResponse
615
     */
616 6
    public function setWebhook(array $params)
617
    {
618 6
        if (filter_var($params['url'], FILTER_VALIDATE_URL) === false) {
619 2
            throw new TelegramSDKException('Invalid URL Provided');
620
        }
621
622 4
        if (parse_url($params['url'], PHP_URL_SCHEME) !== 'https') {
623 2
            throw new TelegramSDKException('Invalid URL, should be a HTTPS url.');
624
        }
625
626 2
        return $this->uploadFile('setWebhook', $params);
627
    }
628
629
    /**
630
     * Returns webhook updates sent by Telegram.
631
     * Works only if you set a webhook.
632
     *
633
     * @see setWebhook
634
     *
635
     * @return Update
636
     */
637
    public function getWebhookUpdates()
638
    {
639
        $body = json_decode(file_get_contents('php://input'), true);
640
641
        return new Update($body);
642
    }
643
644
    /**
645
     * Removes the outgoing webhook (if any).
646
     *
647
     * @return TelegramResponse
648
     */
649 2
    public function removeWebhook()
650
    {
651 2
        $url = '';
652
653 2
        return $this->post('setWebhook', compact('url'));
654
    }
655
656
    /**
657
     * Use this method to receive incoming updates using long polling.
658
     *
659
     * <code>
660
     * $params = [
661
     *   'offset'  => '',
662
     *   'limit'   => '',
663
     *   'timeout' => '',
664
     * ];
665
     * </code>
666
     *
667
     * @link https://core.telegram.org/bots/api#getupdates
668
     *
669
     * @param array  $params
670
     *
671
     * @var int|null $params ['offset']
672
     * @var int|null $params ['limit']
673
     * @var int|null $params ['timeout']
674
     *
675
     * @return Update[]
676
     */
677 6
    public function getUpdates(array $params = [])
678
    {
679 6
        $response = $this->post('getUpdates', $params);
680 6
        $updates = $response->getDecodedBody();
681
682 6
        $data = [];
683 6
        if (isset($updates['result'])) {
684 6
            foreach ($updates['result'] as $update) {
685 6
                $data[] = new Update($update);
686 6
            }
687 6
        }
688
689 6
        return $data;
690
    }
691
692
    /**
693
     * Builds a custom keyboard markup.
694
     *
695
     * <code>
696
     * $params = [
697
     *   'keyboard'          => '',
698
     *   'resize_keyboard'   => '',
699
     *   'one_time_keyboard' => '',
700
     *   'selective'         => '',
701
     * ];
702
     * </code>
703
     *
704
     * @link https://core.telegram.org/bots/api#replykeyboardmarkup
705
     *
706
     * @param array $params
707
     *
708
     * @var array   $params ['keyboard']
709
     * @var bool    $params ['resize_keyboard']
710
     * @var bool    $params ['one_time_keyboard']
711
     * @var bool    $params ['selective']
712
     *
713
     * @return string
714
     */
715 2
    public function replyKeyboardMarkup(array $params)
716
    {
717 2
        return json_encode($params);
718
    }
719
720
    /**
721
     * Hide the current custom keyboard and display the default letter-keyboard.
722
     *
723
     * <code>
724
     * $params = [
725
     *   'hide_keyboard' => true,
726
     *   'selective'     => false,
727
     * ];
728
     * </code>
729
     *
730
     * @link https://core.telegram.org/bots/api#replykeyboardhide
731
     *
732
     * @param array $params
733
     *
734
     * @var bool    $params ['hide_keyboard']
735
     * @var bool    $params ['selective']
736
     *
737
     * @return string
738
     */
739 2
    public static function replyKeyboardHide(array $params = [])
740
    {
741 2
        return json_encode(array_merge(['hide_keyboard' => true, 'selective' => false], $params));
742
    }
743
744
    /**
745
     * Display a reply interface to the user (act as if the user has selected the bot‘s message and tapped ’Reply').
746
     *
747
     * <code>
748
     * $params = [
749
     *   'force_reply' => true,
750
     *   'selective'   => false,
751
     * ];
752
     * </code>
753
     *
754
     * @link https://core.telegram.org/bots/api#forcereply
755
     *
756
     * @param array $params
757
     *
758
     * @var bool    $params ['force_reply']
759
     * @var bool    $params ['selective']
760
     *
761
     * @return string
762
     */
763 2
    public static function forceReply(array $params = [])
764
    {
765 2
        return json_encode(array_merge(['force_reply' => true, 'selective' => false], $params));
766
    }
767
768
    /**
769
     * Processes Inbound Commands.
770
     *
771
     * @param bool $webhook
772
     *
773
     * @return Update|Update[]
774
     */
775 6
    public function commandsHandler($webhook = false)
776
    {
777 6
        if ($webhook) {
778
            $update = $this->getWebhookUpdates();
779
            $this->processCommand($update);
780
781
            return $update;
782
        }
783
784 6
        $updates = $this->getUpdates();
785 6
        $highestId = -1;
786
787 6
        foreach ($updates as $update) {
788 6
            $highestId = $update->getUpdateId();
789 6
            $this->processCommand($update);
790 6
        }
791
792
        //An update is considered confirmed as soon as getUpdates is called with an offset higher than its update_id.
793 6
        if ($highestId != -1) {
794 6
            $params = [];
795 6
            $params['offset'] = $highestId + 1;
796 6
            $params['limit'] = 1;
797 6
            $this->getUpdates($params);
798 6
        }
799
800 6
        return $updates;
801
    }
802
803
    /**
804
     * Check update object for a command and process.
805
     *
806
     * @param Update $update
807
     */
808 6
    protected function processCommand(Update $update)
809
    {
810 6
        $message = $update->getMessage();
811
812 6
        if ($message !== null && $message->has('text')) {
813 6
            $this->getCommandBus()->handler($message->getText(), $update);
814 6
        }
815 6
    }
816
817
    /**
818
     * Determine if a given type is the message.
819
     *
820
     * @param string         $type
821
     * @param Update|Message $object
822
     *
823
     * @return bool
824
     */
825
    public function isMessageType($type, $object)
826
    {
827
        if ($object instanceof Update) {
828
            $object = $object->getMessage();
829
        }
830
831
        if ($object->has(strtolower($type))) {
832
            return true;
833
        }
834
835
        return $this->detectMessageType($object) === $type;
836
    }
837
838
    /**
839
     * Detect Message Type Based on Update or Message Object.
840
     *
841
     * @param Update|Message $object
842
     *
843
     * @return string|null
844
     */
845
    public function detectMessageType($object)
846
    {
847
        if ($object instanceof Update) {
848
            $object = $object->getMessage();
849
        }
850
851
        $types = ['audio', 'document', 'photo', 'sticker', 'video', 'voice', 'contact', 'location', 'text'];
852
853
        return $object->keys()
854
            ->intersect($types)
855
            ->pop();
856
    }
857
858
    /**
859
     * Sends a GET request to Telegram Bot API and returns the result.
860
     *
861
     * @param string $endpoint
862
     * @param array  $params
863
     *
864
     * @throws TelegramSDKException
865
     *
866
     * @return TelegramResponse
867
     */
868
    protected function get($endpoint, $params = [])
869
    {
870
        return $this->sendRequest(
871
            'GET',
872
            $endpoint,
873
            $params
874
        );
875
    }
876
877
    /**
878
     * Sends a POST request to Telegram Bot API and returns the result.
879
     *
880
     * @param string $endpoint
881
     * @param array  $params
882
     * @param bool   $fileUpload Set true if a file is being uploaded.
883
     *
884
     * @return TelegramResponse
885
     */
886 40
    protected function post($endpoint, array $params = [], $fileUpload = false)
887
    {
888 40
        if ($fileUpload) {
889 16
            $params = ['multipart' => $params];
890 16
        } else {
891 24
            $params = ['form_params' => $params];
892
        }
893
894 40
        return $this->sendRequest(
895 40
            'POST',
896 40
            $endpoint,
897
            $params
898 40
        );
899
    }
900
901
    /**
902
     * Sends a multipart/form-data request to Telegram Bot API and returns the result.
903
     * Used primarily for file uploads.
904
     *
905
     * @param string $endpoint
906
     * @param array  $params
907
     *
908
     * @throws TelegramSDKException
909
     *
910
     * @return Message
911
     */
912 16
    protected function uploadFile($endpoint, array $params = [])
913
    {
914 16
        $i = 0;
915 16
        $multipart_params = [];
916 16
        foreach ($params as $name => $contents) {
917 16
            if (is_null($contents)) {
918
                continue;
919
            }
920
921 16
            if (!is_resource($contents) && $name !== 'url') {
922 14
                $validUrl = filter_var($contents, FILTER_VALIDATE_URL);
923 14
                $contents = (is_file($contents) || $validUrl) ? (new InputFile($contents))->open() : (string)$contents;
924 14
            }
925
926 16
            $multipart_params[$i]['name'] = $name;
927 16
            $multipart_params[$i]['contents'] = $contents;
928 16
            ++$i;
929 16
        }
930
931 16
        $response = $this->post($endpoint, $multipart_params, true);
932
933 16
        return new Message($response->getDecodedBody());
934
    }
935
936
    /**
937
     * Sends a request to Telegram Bot API and returns the result.
938
     *
939
     * @param string $method
940
     * @param string $endpoint
941
     * @param array  $params
942
     *
943
     * @throws TelegramSDKException
944
     *
945
     * @return TelegramResponse
946
     */
947 40
    protected function sendRequest(
948
        $method,
949
        $endpoint,
950
        array $params = []
951
    ) {
952 40
        $request = $this->request($method, $endpoint, $params);
953
954 40
        return $this->lastResponse = $this->client->sendRequest($request);
955
    }
956
957
    /**
958
     * Instantiates a new TelegramRequest entity.
959
     *
960
     * @param string $method
961
     * @param string $endpoint
962
     * @param array  $params
963
     *
964
     * @return TelegramRequest
965
     */
966 40
    protected function request(
967
        $method,
968
        $endpoint,
969
        array $params = []
970
    ) {
971 40
        return new TelegramRequest(
972 40
            $this->getAccessToken(),
973 40
            $method,
974 40
            $endpoint,
975 40
            $params,
976 40
            $this->isAsyncRequest(),
977 40
            $this->getTimeOut(),
978 40
            $this->getConnectTimeOut()
979 40
        );
980
    }
981
982
    /**
983
     * Magic method to process any "get" requests.
984
     *
985
     * @param $method
986
     * @param $arguments
987
     *
988
     * @return bool|TelegramResponse
989
     */
990 2
    public function __call($method, $arguments)
991
    {
992 2
        if (preg_match('/^\w+Commands?/', $method, $matches)) {
993 2
            return call_user_func_array([$this->getCommandBus(), $matches[0]], $arguments);
994
        }
995
996
        $action = substr($method, 0, 3);
997
        if ($action === 'get') {
998
            /* @noinspection PhpUndefinedFunctionInspection */
999
            $class_name = studly_case(substr($method, 3));
1000
            $class = 'Telegram\Bot\Objects\\'.$class_name;
1001
            $response = $this->post($method, $arguments[0] ?: []);
1002
1003
            if (class_exists($class)) {
1004
                return new $class($response->getDecodedBody());
1005
            }
1006
1007
            return $response;
1008
        }
1009
1010
        return false;
1011
    }
1012
1013
    /**
1014
     * Set the IoC Container.
1015
     *
1016
     * @param $container Container instance
1017
     *
1018
     * @return void
1019
     */
1020 2
    public static function setContainer(Container $container)
1021
    {
1022 2
        self::$container = $container;
1023 2
    }
1024
1025
    /**
1026
     * Get the IoC Container.
1027
     *
1028
     * @return Container
1029
     */
1030 2
    public function getContainer()
1031
    {
1032 2
        return self::$container;
1033
    }
1034
1035
    /**
1036
     * Check if IoC Container has been set.
1037
     *
1038
     * @return boolean
1039
     */
1040
    public function hasContainer()
1041
    {
1042
        return self::$container !== null;
1043
    }
1044
1045
    /**
1046
     * @return int
1047
     */
1048 40
    public function getTimeOut()
1049
    {
1050 40
        return $this->timeOut;
1051
    }
1052
1053
    /**
1054
     * @param int $timeOut
1055
     *
1056
     * @return $this
1057
     */
1058 2
    public function setTimeOut($timeOut)
1059
    {
1060 2
        $this->timeOut = $timeOut;
1061
1062 2
        return $this;
1063
    }
1064
1065
    /**
1066
     * @return int
1067
     */
1068 40
    public function getConnectTimeOut()
1069
    {
1070 40
        return $this->connectTimeOut;
1071
    }
1072
1073
    /**
1074
     * @param int $connectTimeOut
1075
     *
1076
     * @return $this
1077
     */
1078 2
    public function setConnectTimeOut($connectTimeOut)
1079
    {
1080 2
        $this->connectTimeOut = $connectTimeOut;
1081
1082 2
        return $this;
1083
    }
1084
}
1085