Completed
Push — master ( 380288...32190c )
by Gusev
07:27 queued 10s
created

BotApi::sendAnimation()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 21

Duplication

Lines 21
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 21
loc 21
ccs 0
cts 10
cp 0
rs 9.584
c 0
b 0
f 0
cc 2
nc 1
nop 8
crap 6

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace TelegramBot\Api;
4
5
use TelegramBot\Api\Types\ArrayOfChatMemberEntity;
6
use TelegramBot\Api\Types\ArrayOfMessages;
7
use TelegramBot\Api\Types\ArrayOfUpdates;
8
use TelegramBot\Api\Types\Chat;
9
use TelegramBot\Api\Types\ChatMember;
10
use TelegramBot\Api\Types\File;
11
use TelegramBot\Api\Types\Inline\QueryResult\AbstractInlineQueryResult;
12
use TelegramBot\Api\Types\InputMedia\ArrayOfInputMedia;
13
use TelegramBot\Api\Types\Message;
14
use TelegramBot\Api\Types\Poll;
15
use TelegramBot\Api\Types\Update;
16
use TelegramBot\Api\Types\User;
17
use TelegramBot\Api\Types\UserProfilePhotos;
18
19
/**
20
 * Class BotApi
21
 *
22
 * @package TelegramBot\Api
23
 */
24
class BotApi
25
{
26
    /**
27
     * HTTP codes
28
     *
29
     * @var array
30
     */
31
    public static $codes = [
32
        // Informational 1xx
33
        100 => 'Continue',
34
        101 => 'Switching Protocols',
35
        102 => 'Processing',            // RFC2518
36
        // Success 2xx
37
        200 => 'OK',
38
        201 => 'Created',
39
        202 => 'Accepted',
40
        203 => 'Non-Authoritative Information',
41
        204 => 'No Content',
42
        205 => 'Reset Content',
43
        206 => 'Partial Content',
44
        207 => 'Multi-Status',          // RFC4918
45
        208 => 'Already Reported',      // RFC5842
46
        226 => 'IM Used',               // RFC3229
47
        // Redirection 3xx
48
        300 => 'Multiple Choices',
49
        301 => 'Moved Permanently',
50
        302 => 'Found', // 1.1
51
        303 => 'See Other',
52
        304 => 'Not Modified',
53
        305 => 'Use Proxy',
54
        // 306 is deprecated but reserved
55
        307 => 'Temporary Redirect',
56
        308 => 'Permanent Redirect',    // RFC7238
57
        // Client Error 4xx
58
        400 => 'Bad Request',
59
        401 => 'Unauthorized',
60
        402 => 'Payment Required',
61
        403 => 'Forbidden',
62
        404 => 'Not Found',
63
        405 => 'Method Not Allowed',
64
        406 => 'Not Acceptable',
65
        407 => 'Proxy Authentication Required',
66
        408 => 'Request Timeout',
67
        409 => 'Conflict',
68
        410 => 'Gone',
69
        411 => 'Length Required',
70
        412 => 'Precondition Failed',
71
        413 => 'Payload Too Large',
72
        414 => 'URI Too Long',
73
        415 => 'Unsupported Media Type',
74
        416 => 'Range Not Satisfiable',
75
        417 => 'Expectation Failed',
76
        422 => 'Unprocessable Entity',                                        // RFC4918
77
        423 => 'Locked',                                                      // RFC4918
78
        424 => 'Failed Dependency',                                           // RFC4918
79
        425 => 'Reserved for WebDAV advanced collections expired proposal',   // RFC2817
80
        426 => 'Upgrade Required',                                            // RFC2817
81
        428 => 'Precondition Required',                                       // RFC6585
82
        429 => 'Too Many Requests',                                           // RFC6585
83
        431 => 'Request Header Fields Too Large',                             // RFC6585
84
        // Server Error 5xx
85
        500 => 'Internal Server Error',
86
        501 => 'Not Implemented',
87
        502 => 'Bad Gateway',
88
        503 => 'Service Unavailable',
89
        504 => 'Gateway Timeout',
90
        505 => 'HTTP Version Not Supported',
91
        506 => 'Variant Also Negotiates (Experimental)',                      // RFC2295
92
        507 => 'Insufficient Storage',                                        // RFC4918
93
        508 => 'Loop Detected',                                               // RFC5842
94
        510 => 'Not Extended',                                                // RFC2774
95
        511 => 'Network Authentication Required',                             // RFC6585
96
    ];
97
98
    private $proxySettings = [];
99
100
    /**
101
     * Default http status code
102
     */
103
    const DEFAULT_STATUS_CODE = 200;
104
105
    /**
106
     * Not Modified http status code
107
     */
108
    const NOT_MODIFIED_STATUS_CODE = 304;
109
110
    /**
111
     * Limits for tracked ids
112
     */
113
    const MAX_TRACKED_EVENTS = 200;
114
115
    /**
116
     * Url prefixes
117
     */
118
    const URL_PREFIX = 'https://api.telegram.org/bot';
119
120
    /**
121
     * Url prefix for files
122
     */
123
    const FILE_URL_PREFIX = 'https://api.telegram.org/file/bot';
124
125
    /**
126
     * CURL object
127
     *
128
     * @var
129
     */
130
    protected $curl;
131
132
    /**
133
     * CURL custom options
134
     *
135
     * @var array
136
     */
137
    protected $customCurlOptions = [];
138
139
    /**
140
     * Bot token
141
     *
142
     * @var string
143
     */
144
    protected $token;
145
146
    /**
147
     * Botan tracker
148
     *
149
     * @var \TelegramBot\Api\Botan
150
     */
151
    protected $tracker;
152
153
    /**
154
     * list of event ids
155
     *
156
     * @var array
157
     */
158
    protected $trackedEvents = [];
159
160
    /**
161
     * Check whether return associative array
162
     *
163
     * @var bool
164
     */
165
    protected $returnArray = true;
166
167
    /**
168
     * Constructor
169
     *
170
     * @param string $token Telegram Bot API token
171
     * @param string|null $trackerToken Yandex AppMetrica application api_key
172
     */
173 9
    public function __construct($token, $trackerToken = null)
174
    {
175 9
        $this->curl = curl_init();
176 9
        $this->token = $token;
177
178 9
        if ($trackerToken) {
179
            $this->tracker = new Botan($trackerToken);
180
        }
181 9
    }
182
183
    /**
184
     * Set return array
185
     *
186
     * @param bool $mode
187
     *
188
     * @return $this
189
     */
190
    public function setModeObject($mode = true)
191
    {
192
        $this->returnArray = !$mode;
193
194
        return $this;
195
    }
196
197
198
    /**
199
     * Call method
200
     *
201
     * @param string $method
202
     * @param array|null $data
203
     *
204
     * @return mixed
205
     * @throws \TelegramBot\Api\Exception
206
     * @throws \TelegramBot\Api\HttpException
207
     * @throws \TelegramBot\Api\InvalidJsonException
208
     */
209
    public function call($method, array $data = null)
210
    {
211
        $options = $this->proxySettings + [
212
            CURLOPT_URL => $this->getUrl().'/'.$method,
213
            CURLOPT_RETURNTRANSFER => true,
214
            CURLOPT_POST => null,
215
            CURLOPT_POSTFIELDS => null,
216
            CURLOPT_TIMEOUT => 5,
217
        ];
218
219
        if ($data) {
220
            $options[CURLOPT_POST] = true;
221
            $options[CURLOPT_POSTFIELDS] = $data;
222
        }
223
224
        if (!empty($this->customCurlOptions) && is_array($this->customCurlOptions)) {
225
            $options = $this->customCurlOptions + $options;
226
        }
227
228
        $response = self::jsonValidate($this->executeCurl($options), $this->returnArray);
229
230
        if ($this->returnArray) {
231
            if (!isset($response['ok']) || !$response['ok']) {
232
                throw new Exception($response['description'], $response['error_code']);
233
            }
234
235
            return $response['result'];
236
        }
237
238
        if (!$response->ok) {
239
            throw new Exception($response->description, $response->error_code);
240
        }
241
242
        return $response->result;
243
    }
244
245
    /**
246
     * curl_exec wrapper for response validation
247
     *
248
     * @param array $options
249
     *
250
     * @return string
251
     *
252
     * @throws \TelegramBot\Api\HttpException
253
     */
254
    protected function executeCurl(array $options)
255
    {
256
        curl_setopt_array($this->curl, $options);
257
258
        $result = curl_exec($this->curl);
259
        self::curlValidate($this->curl, $result);
260
        if ($result === false) {
261
            throw new HttpException(curl_error($this->curl), curl_errno($this->curl));
262
        }
263
264
        return $result;
265
    }
266
267
    /**
268
     * Response validation
269
     *
270
     * @param resource $curl
271
     * @param string $response
272
     * @throws HttpException
273
     */
274
    public static function curlValidate($curl, $response = null)
275
    {
276
        $json = json_decode($response, true)?: [];
277
        if (($httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE))
278
            && !in_array($httpCode, [self::DEFAULT_STATUS_CODE, self::NOT_MODIFIED_STATUS_CODE])
279
        ) {
280
            $errorDescription = array_key_exists('description', $json) ? $json['description'] : self::$codes[$httpCode];
281
            $errorParameters = array_key_exists('parameters', $json) ? $json['parameters'] : [];
282
            throw new HttpException($errorDescription, $httpCode, null, $errorParameters);
283
        }
284
    }
285
286
    /**
287
     * JSON validation
288
     *
289
     * @param string $jsonString
290
     * @param boolean $asArray
291
     *
292
     * @return object|array
293
     * @throws \TelegramBot\Api\InvalidJsonException
294
     */
295
    public static function jsonValidate($jsonString, $asArray)
296
    {
297
        $json = json_decode($jsonString, $asArray);
298
299
        if (json_last_error() != JSON_ERROR_NONE) {
300
            throw new InvalidJsonException(json_last_error_msg(), json_last_error());
301
        }
302
303
        return $json;
304
    }
305
306
    /**
307
     * Use this method to send text messages. On success, the sent \TelegramBot\Api\Types\Message is returned.
308
     *
309
     * @param int|string $chatId
310
     * @param string $text
311
     * @param string|null $parseMode
312
     * @param bool $disablePreview
313
     * @param int|null $replyToMessageId
314
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
315
     *        Types\ReplyKeyboardRemove|null $replyMarkup
316
     * @param bool $disableNotification
317
     *
318
     * @return \TelegramBot\Api\Types\Message
319
     * @throws \TelegramBot\Api\InvalidArgumentException
320
     * @throws \TelegramBot\Api\Exception
321
     */
322 View Code Duplication
    public function sendMessage(
323
        $chatId,
324
        $text,
325
        $parseMode = null,
326
        $disablePreview = false,
327
        $replyToMessageId = null,
328
        $replyMarkup = null,
329
        $disableNotification = false
330
    ) {
331
        return Message::fromResponse($this->call('sendMessage', [
332
            'chat_id' => $chatId,
333
            'text' => $text,
334
            'parse_mode' => $parseMode,
335
            'disable_web_page_preview' => $disablePreview,
336
            'reply_to_message_id' => (int)$replyToMessageId,
337
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
338
            'disable_notification' => (bool)$disableNotification,
339
        ]));
340
    }
341
342
    /**
343
     * Use this method to send phone contacts
344
     *
345
     * @param int|string $chatId chat_id or @channel_name
346
     * @param string $phoneNumber
347
     * @param string $firstName
348
     * @param string $lastName
349
     * @param int|null $replyToMessageId
350
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
351
     *        Types\ReplyKeyboardRemove|null $replyMarkup
352
     * @param bool $disableNotification
353
     *
354
     * @return \TelegramBot\Api\Types\Message
355
     * @throws \TelegramBot\Api\Exception
356
     */
357 View Code Duplication
    public function sendContact(
358
        $chatId,
359
        $phoneNumber,
360
        $firstName,
361
        $lastName = null,
362
        $replyToMessageId = null,
363
        $replyMarkup = null,
364
        $disableNotification = false
365
    ) {
366
        return Message::fromResponse($this->call('sendContact', [
367
            'chat_id' => $chatId,
368
            'phone_number' => $phoneNumber,
369
            'first_name' => $firstName,
370
            'last_name' => $lastName,
371
            'reply_to_message_id' => $replyToMessageId,
372
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
373
            'disable_notification' => (bool)$disableNotification,
374
        ]));
375
    }
376
377
    /**
378
     * Use this method when you need to tell the user that something is happening on the bot's side.
379
     * The status is set for 5 seconds or less (when a message arrives from your bot,
380
     * Telegram clients clear its typing status).
381
     *
382
     * We only recommend using this method when a response from the bot will take a noticeable amount of time to arrive.
383
     *
384
     * Type of action to broadcast. Choose one, depending on what the user is about to receive:
385
     * `typing` for text messages, `upload_photo` for photos, `record_video` or `upload_video` for videos,
386
     * `record_audio` or upload_audio for audio files, `upload_document` for general files,
387
     * `find_location` for location data.
388
     *
389
     * @param int $chatId
390
     * @param string $action
391
     *
392
     * @return bool
393
     * @throws \TelegramBot\Api\Exception
394
     */
395
    public function sendChatAction($chatId, $action)
396
    {
397
        return $this->call('sendChatAction', [
398
            'chat_id' => $chatId,
399
            'action' => $action,
400
        ]);
401
    }
402
403
    /**
404
     * Use this method to get a list of profile pictures for a user.
405
     *
406
     * @param int $userId
407
     * @param int $offset
408
     * @param int $limit
409
     *
410
     * @return \TelegramBot\Api\Types\UserProfilePhotos
411
     * @throws \TelegramBot\Api\Exception
412
     */
413
    public function getUserProfilePhotos($userId, $offset = 0, $limit = 100)
414
    {
415
        return UserProfilePhotos::fromResponse($this->call('getUserProfilePhotos', [
416
            'user_id' => (int)$userId,
417
            'offset' => (int)$offset,
418
            'limit' => (int)$limit,
419
        ]));
420
    }
421
422
    /**
423
     * Use this method to specify a url and receive incoming updates via an outgoing webhook.
424
     * Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url,
425
     * containing a JSON-serialized Update.
426
     * In case of an unsuccessful request, we will give up after a reasonable amount of attempts.
427
     *
428
     * @param string $url HTTPS url to send updates to. Use an empty string to remove webhook integration
429
     * @param \CURLFile|string $certificate Upload your public key certificate
430
     *                                      so that the root certificate in use can be checked
431
     *
432
     * @return string
433
     *
434
     * @throws \TelegramBot\Api\Exception
435
     */
436
    public function setWebhook($url = '', $certificate = null)
437
    {
438
        return $this->call('setWebhook', ['url' => $url, 'certificate' => $certificate]);
439
    }
440
    
441
    
442
    /**
443
     * Use this method to clear webhook and use getUpdates again!
444
     *
445
     * @return mixed
446
     *
447
     * @throws \TelegramBot\Api\Exception
448
     */
449
    public function deleteWebhook()
450
    {
451
        return $this->call('deleteWebhook');
452
    }
453
454
    /**
455
     * A simple method for testing your bot's auth token.Requires no parameters.
456
     * Returns basic information about the bot in form of a User object.
457
     *
458
     * @return \TelegramBot\Api\Types\User
459
     * @throws \TelegramBot\Api\Exception
460
     * @throws \TelegramBot\Api\InvalidArgumentException
461
     */
462
    public function getMe()
463
    {
464
        return User::fromResponse($this->call('getMe'));
465
    }
466
467
    /**
468
     * Use this method to receive incoming updates using long polling.
469
     * An Array of Update objects is returned.
470
     *
471
     * Notes
472
     * 1. This method will not work if an outgoing webhook is set up.
473
     * 2. In order to avoid getting duplicate updates, recalculate offset after each server response.
474
     *
475
     * @param int $offset
476
     * @param int $limit
477
     * @param int $timeout
478
     *
479
     * @return Update[]
480
     * @throws \TelegramBot\Api\Exception
481
     * @throws \TelegramBot\Api\InvalidArgumentException
482
     */
483 2
    public function getUpdates($offset = 0, $limit = 100, $timeout = 0)
484
    {
485 2
        $updates = ArrayOfUpdates::fromResponse($this->call('getUpdates', [
486 2
            'offset' => $offset,
487 2
            'limit' => $limit,
488 2
            'timeout' => $timeout,
489 2
        ]));
490
491 2
        if ($this->tracker instanceof Botan) {
492
            foreach ($updates as $update) {
493
                $this->trackUpdate($update);
494
            }
495
        }
496
497 2
        return $updates;
498
    }
499
500
    /**
501
     * Use this method to send point on the map. On success, the sent Message is returned.
502
     *
503
     * @param int|string                                                              $chatId
504
     * @param float                                                                   $latitude
505
     * @param float                                                                   $longitude
506
     * @param int|null                                                                $replyToMessageId
507
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
508
     *        Types\ReplyKeyboardRemove|null $replyMarkup
509
     * @param bool                                                                    $disableNotification
510
     *
511
     * @param null|int                                                                $livePeriod
512
     * @return \TelegramBot\Api\Types\Message
513
     */
514 View Code Duplication
    public function sendLocation(
515
        $chatId,
516
        $latitude,
517
        $longitude,
518
        $replyToMessageId = null,
519
        $replyMarkup = null,
520
        $disableNotification = false,
521
        $livePeriod = null
522
    ) {
523
        return Message::fromResponse($this->call('sendLocation', [
524
            'chat_id'              => $chatId,
525
            'latitude'             => $latitude,
526
            'longitude'            => $longitude,
527
            'live_period'          => $livePeriod,
528
            'reply_to_message_id'  => $replyToMessageId,
529
            'reply_markup'         => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
530
            'disable_notification' => (bool)$disableNotification,
531
        ]));
532
    }
533
534
    /**
535
     * Use this method to edit live location messages sent by the bot or via the bot (for inline bots).
536
     *
537
     * @param int|string                                                              $chatId
538
     * @param int                                                                     $messageId
539
     * @param string                                                                  $inlineMessageId
540
     * @param float                                                                   $latitude
541
     * @param float                                                                   $longitude
542
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
543
     *        Types\ReplyKeyboardRemove|null $replyMarkup
544
     * @return \TelegramBot\Api\Types\Message
545
     */
546
    public function editMessageLiveLocation(
547
        $chatId,
548
        $messageId,
549
        $inlineMessageId,
550
        $latitude,
551
        $longitude,
552
        $replyMarkup = null
553
    ) {
554
        return Message::fromResponse($this->call('sendLocation', [
555
            'chat_id'           => $chatId,
556
            'message_id'        => $messageId,
557
            'inline_message_id' => $inlineMessageId,
558
            'latitude'          => $latitude,
559
            'longitude'         => $longitude,
560
            'reply_markup'      => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
561
        ]));
562
    }
563
564
    /**
565
     * Use this method to stop updating a live location message sent by the bot or via the bot (for inline bots) before
566
     * live_period expires.
567
     *
568
     * @param int|string                                                              $chatId
569
     * @param int                                                                     $messageId
570
     * @param string                                                                  $inlineMessageId
571
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
572
     *        Types\ReplyKeyboardRemove|null $replyMarkup
573
     * @return \TelegramBot\Api\Types\Message
574
     */
575 View Code Duplication
    public function stopMessageLiveLocation(
576
        $chatId,
577
        $messageId,
578
        $inlineMessageId,
579
        $replyMarkup = null
580
    ) {
581
        return Message::fromResponse($this->call('sendLocation', [
582
            'chat_id'           => $chatId,
583
            'message_id'        => $messageId,
584
            'inline_message_id' => $inlineMessageId,
585
            'reply_markup'      => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
586
        ]));
587
    }
588
589
    /**
590
     * Use this method to send information about a venue. On success, the sent Message is returned.
591
     *
592
     * @param int|string $chatId chat_id or @channel_name
593
     * @param float $latitude
594
     * @param float $longitude
595
     * @param string $title
596
     * @param string $address
597
     * @param string|null $foursquareId
598
     * @param int|null $replyToMessageId
599
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
600
     *        Types\ReplyKeyboardRemove|null $replyMarkup
601
     * @param bool $disableNotification
602
     *
603
     * @return \TelegramBot\Api\Types\Message
604
     * @throws \TelegramBot\Api\Exception
605
     */
606
    public function sendVenue(
607
        $chatId,
608
        $latitude,
609
        $longitude,
610
        $title,
611
        $address,
612
        $foursquareId = null,
613
        $replyToMessageId = null,
614
        $replyMarkup = null,
615
        $disableNotification = false
616
    ) {
617
        return Message::fromResponse($this->call('sendVenue', [
618
            'chat_id' => $chatId,
619
            'latitude' => $latitude,
620
            'longitude' => $longitude,
621
            'title' => $title,
622
            'address' => $address,
623
            'foursquare_id' => $foursquareId,
624
            'reply_to_message_id' => $replyToMessageId,
625
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
626
            'disable_notification' => (bool)$disableNotification,
627
        ]));
628
    }
629
630
    /**
631
     * Use this method to send .webp stickers. On success, the sent Message is returned.
632
     *
633
     * @param int|string $chatId chat_id or @channel_name
634
     * @param \CURLFile|string $sticker
635
     * @param int|null $replyToMessageId
636
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
637
     *        Types\ReplyKeyboardRemove|null $replyMarkup
638
     * @param bool $disableNotification
639
     *
640
     * @return \TelegramBot\Api\Types\Message
641
     * @throws \TelegramBot\Api\InvalidArgumentException
642
     * @throws \TelegramBot\Api\Exception
643
     */
644 View Code Duplication
    public function sendSticker(
645
        $chatId,
646
        $sticker,
647
        $replyToMessageId = null,
648
        $replyMarkup = null,
649
        $disableNotification = false
650
    ) {
651
        return Message::fromResponse($this->call('sendSticker', [
652
            'chat_id' => $chatId,
653
            'sticker' => $sticker,
654
            'reply_to_message_id' => $replyToMessageId,
655
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
656
            'disable_notification' => (bool)$disableNotification,
657
        ]));
658
    }
659
660
    /**
661
     * Use this method to send video files,
662
     * Telegram clients support mp4 videos (other formats may be sent as Document).
663
     * On success, the sent Message is returned.
664
     *
665
     * @param int|string $chatId chat_id or @channel_name
666
     * @param \CURLFile|string $video
667
     * @param int|null $duration
668
     * @param string|null $caption
669
     * @param int|null $replyToMessageId
670
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
671
     *        Types\ReplyKeyboardRemove|null $replyMarkup
672
     * @param bool $disableNotification
673
     * @param bool $supportsStreaming Pass True, if the uploaded video is suitable for streaming
674
     * @param string|null $parseMode
675
     *
676
     * @return \TelegramBot\Api\Types\Message
677
     * @throws \TelegramBot\Api\InvalidArgumentException
678
     * @throws \TelegramBot\Api\Exception
679
     */
680 View Code Duplication
    public function sendVideo(
681
        $chatId,
682
        $video,
683
        $duration = null,
684
        $caption = null,
685
        $replyToMessageId = null,
686
        $replyMarkup = null,
687
        $disableNotification = false,
688
        $supportsStreaming = false,
689
        $parseMode = null
690
    ) {
691
        return Message::fromResponse($this->call('sendVideo', [
692
            'chat_id' => $chatId,
693
            'video' => $video,
694
            'duration' => $duration,
695
            'caption' => $caption,
696
            'reply_to_message_id' => $replyToMessageId,
697
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
698
            'disable_notification' => (bool)$disableNotification,
699
            'supports_streaming' => (bool)$supportsStreaming,
700
            'parse_mode' => $parseMode
701
        ]));
702
    }
703
704
    /**
705
     * Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound),
706
     * On success, the sent Message is returned.
707
     * Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future.
708
     *
709
     * @param int|string $chatId chat_id or @channel_name
710
     * @param \CURLFile|string $animation
711
     * @param int|null $duration
712
     * @param string|null $caption
713
     * @param int|null $replyToMessageId
714
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
715
     *        Types\ReplyKeyboardRemove|null $replyMarkup
716
     * @param bool $disableNotification
717
     * @param string|null $parseMode
718
     *
719
     * @return \TelegramBot\Api\Types\Message
720
     * @throws \TelegramBot\Api\InvalidArgumentException
721
     * @throws \TelegramBot\Api\Exception
722
     */
723 View Code Duplication
    public function sendAnimation(
724
        $chatId,
725
        $animation,
726
        $duration = null,
727
        $caption = null,
728
        $replyToMessageId = null,
729
        $replyMarkup = null,
730
        $disableNotification = false,
731
        $parseMode = null
732
    ) {
733
        return Message::fromResponse($this->call('sendAnimation', [
734
            'chat_id' => $chatId,
735
            'animation' => $animation,
736
            'duration' => $duration,
737
            'caption' => $caption,
738
            'reply_to_message_id' => $replyToMessageId,
739
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
740
            'disable_notification' => (bool)$disableNotification,
741
            'parse_mode' => $parseMode
742
        ]));
743
    }
744
745
    /**
746
     * Use this method to send audio files,
747
     * if you want Telegram clients to display the file as a playable voice message.
748
     * For this to work, your audio must be in an .ogg file encoded with OPUS
749
     * (other formats may be sent as Audio or Document).
750
     * On success, the sent Message is returned.
751
     * Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future.
752
     *
753
     * @param int|string $chatId chat_id or @channel_name
754
     * @param \CURLFile|string $voice
755
     * @param int|null $duration
756
     * @param int|null $replyToMessageId
757
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
758
     *        Types\ReplyKeyboardRemove|null $replyMarkup
759
     * @param bool $disableNotification
760
     * @param string|null $parseMode
761
     *
762
     * @return \TelegramBot\Api\Types\Message
763
     * @throws \TelegramBot\Api\InvalidArgumentException
764
     * @throws \TelegramBot\Api\Exception
765
     */
766 View Code Duplication
    public function sendVoice(
767
        $chatId,
768
        $voice,
769
        $duration = null,
770
        $replyToMessageId = null,
771
        $replyMarkup = null,
772
        $disableNotification = false,
773
        $parseMode = null
774
    ) {
775
        return Message::fromResponse($this->call('sendVoice', [
776
            'chat_id' => $chatId,
777
            'voice' => $voice,
778
            'duration' => $duration,
779
            'reply_to_message_id' => $replyToMessageId,
780
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
781
            'disable_notification' => (bool)$disableNotification,
782
            'parse_mode' => $parseMode
783
        ]));
784
    }
785
786
    /**
787
     * Use this method to forward messages of any kind. On success, the sent Message is returned.
788
     *
789
     * @param int|string $chatId chat_id or @channel_name
790
     * @param int $fromChatId
791
     * @param int $messageId
792
     * @param bool $disableNotification
793
     *
794
     * @return \TelegramBot\Api\Types\Message
795
     * @throws \TelegramBot\Api\InvalidArgumentException
796
     * @throws \TelegramBot\Api\Exception
797
     */
798
    public function forwardMessage($chatId, $fromChatId, $messageId, $disableNotification = false)
799
    {
800
        return Message::fromResponse($this->call('forwardMessage', [
801
            'chat_id' => $chatId,
802
            'from_chat_id' => $fromChatId,
803
            'message_id' => (int)$messageId,
804
            'disable_notification' => (bool)$disableNotification,
805
        ]));
806
    }
807
808
    /**
809
     * Use this method to send audio files,
810
     * if you want Telegram clients to display them in the music player.
811
     * Your audio must be in the .mp3 format.
812
     * On success, the sent Message is returned.
813
     * Bots can currently send audio files of up to 50 MB in size, this limit may be changed in the future.
814
     *
815
     * For backward compatibility, when the fields title and performer are both empty
816
     * and the mime-type of the file to be sent is not audio/mpeg, the file will be sent as a playable voice message.
817
     * For this to work, the audio must be in an .ogg file encoded with OPUS.
818
     * This behavior will be phased out in the future. For sending voice messages, use the sendVoice method instead.
819
     *
820
     * @deprecated since 20th February. Removed backward compatibility from the method sendAudio.
821
     * Voice messages now must be sent using the method sendVoice.
822
     * There is no more need to specify a non-empty title or performer while sending the audio by file_id.
823
     *
824
     * @param int|string $chatId chat_id or @channel_name
825
     * @param \CURLFile|string $audio
826
     * @param int|null $duration
827
     * @param string|null $performer
828
     * @param string|null $title
829
     * @param int|null $replyToMessageId
830
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
831
     *        Types\ReplyKeyboardRemove|null $replyMarkup
832
     * @param bool $disableNotification
833
     * @param string|null $parseMode
834
     *
835
     * @return \TelegramBot\Api\Types\Message
836
     * @throws \TelegramBot\Api\InvalidArgumentException
837
     * @throws \TelegramBot\Api\Exception
838
     */
839 View Code Duplication
    public function sendAudio(
840
        $chatId,
841
        $audio,
842
        $duration = null,
843
        $performer = null,
844
        $title = null,
845
        $replyToMessageId = null,
846
        $replyMarkup = null,
847
        $disableNotification = false,
848
        $parseMode = null
849
    ) {
850
        return Message::fromResponse($this->call('sendAudio', [
851
            'chat_id' => $chatId,
852
            'audio' => $audio,
853
            'duration' => $duration,
854
            'performer' => $performer,
855
            'title' => $title,
856
            'reply_to_message_id' => $replyToMessageId,
857
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
858
            'disable_notification' => (bool)$disableNotification,
859
            'parse_mode' => $parseMode
860
        ]));
861
    }
862
863
    /**
864
     * Use this method to send photos. On success, the sent Message is returned.
865
     *
866
     * @param int|string $chatId chat_id or @channel_name
867
     * @param \CURLFile|string $photo
868
     * @param string|null $caption
869
     * @param int|null $replyToMessageId
870
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
871
     *        Types\ReplyKeyboardRemove|null $replyMarkup
872
     * @param bool $disableNotification
873
     * @param string|null $parseMode
874
     *
875
     * @return \TelegramBot\Api\Types\Message
876
     * @throws \TelegramBot\Api\InvalidArgumentException
877
     * @throws \TelegramBot\Api\Exception
878
     */
879 View Code Duplication
    public function sendPhoto(
880
        $chatId,
881
        $photo,
882
        $caption = null,
883
        $replyToMessageId = null,
884
        $replyMarkup = null,
885
        $disableNotification = false,
886
        $parseMode = null
887
    ) {
888
        return Message::fromResponse($this->call('sendPhoto', [
889
            'chat_id' => $chatId,
890
            'photo' => $photo,
891
            'caption' => $caption,
892
            'reply_to_message_id' => $replyToMessageId,
893
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
894
            'disable_notification' => (bool)$disableNotification,
895
            'parse_mode' => $parseMode
896
        ]));
897
    }
898
899
    /**
900
     * Use this method to send general files. On success, the sent Message is returned.
901
     * Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future.
902
     *
903
     * @param int|string $chatId chat_id or @channel_name
904
     * @param \CURLFile|string $document
905
     * @param string|null $caption
906
     * @param int|null $replyToMessageId
907
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
908
     *        Types\ReplyKeyboardRemove|null $replyMarkup
909
     * @param bool $disableNotification
910
     * @param string|null $parseMode
911
     *
912
     * @return \TelegramBot\Api\Types\Message
913
     * @throws \TelegramBot\Api\InvalidArgumentException
914
     * @throws \TelegramBot\Api\Exception
915
     */
916 View Code Duplication
    public function sendDocument(
917
        $chatId,
918
        $document,
919
        $caption = null,
920
        $replyToMessageId = null,
921
        $replyMarkup = null,
922
        $disableNotification = false,
923
        $parseMode = null
924
    ) {
925
        return Message::fromResponse($this->call('sendDocument', [
926
            'chat_id' => $chatId,
927
            'document' => $document,
928
            'caption' => $caption,
929
            'reply_to_message_id' => $replyToMessageId,
930
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
931
            'disable_notification' => (bool)$disableNotification,
932
            'parse_mode' => $parseMode
933
        ]));
934
    }
935
936
    /**
937
     * Use this method to get basic info about a file and prepare it for downloading.
938
     * For the moment, bots can download files of up to 20MB in size.
939
     * On success, a File object is returned.
940
     * The file can then be downloaded via the link https://api.telegram.org/file/bot<token>/<file_path>,
941
     * where <file_path> is taken from the response.
942
     * It is guaranteed that the link will be valid for at least 1 hour.
943
     * When the link expires, a new one can be requested by calling getFile again.
944
     *
945
     * @param $fileId
946
     *
947
     * @return \TelegramBot\Api\Types\File
948
     * @throws \TelegramBot\Api\InvalidArgumentException
949
     * @throws \TelegramBot\Api\Exception
950
     */
951
    public function getFile($fileId)
952
    {
953
        return File::fromResponse($this->call('getFile', ['file_id' => $fileId]));
954
    }
955
956
    /**
957
     * Get file contents via cURL
958
     *
959
     * @param $fileId
960
     *
961
     * @return string
962
     *
963
     * @throws \TelegramBot\Api\HttpException
964
     */
965
    public function downloadFile($fileId)
966
    {
967
        $file = $this->getFile($fileId);
968
        $options = [
969
            CURLOPT_HEADER => 0,
970
            CURLOPT_HTTPGET => 1,
971
            CURLOPT_RETURNTRANSFER => 1,
972
            CURLOPT_URL => $this->getFileUrl().'/'.$file->getFilePath(),
973
        ];
974
975
        return $this->executeCurl($options);
976
    }
977
978
    /**
979
     * Use this method to send answers to an inline query. On success, True is returned.
980
     * No more than 50 results per query are allowed.
981
     *
982
     * @param string $inlineQueryId
983
     * @param AbstractInlineQueryResult[] $results
984
     * @param int $cacheTime
985
     * @param bool $isPersonal
986
     * @param string $nextOffset
987
     * @param string $switchPmText
988
     * @param string $switchPmParameter
989
     *
990
     * @return mixed
991
     * @throws Exception
992
     */
993
    public function answerInlineQuery(
994
        $inlineQueryId,
995
        $results,
996
        $cacheTime = 300,
997
        $isPersonal = false,
998
        $nextOffset = '',
999
        $switchPmText = null,
1000
        $switchPmParameter = null
1001
    ) {
1002
        $results = array_map(function ($item) {
1003
            /* @var AbstractInlineQueryResult $item */
1004
            return json_decode($item->toJson(), true);
1005
        }, $results);
1006
1007
        return $this->call('answerInlineQuery', [
1008
            'inline_query_id' => $inlineQueryId,
1009
            'results' => json_encode($results),
1010
            'cache_time' => $cacheTime,
1011
            'is_personal' => $isPersonal,
1012
            'next_offset' => $nextOffset,
1013
            'switch_pm_text' => $switchPmText,
1014
            'switch_pm_parameter' => $switchPmParameter,
1015
        ]);
1016
    }
1017
1018
    /**
1019
     * Use this method to kick a user from a group or a supergroup.
1020
     * In the case of supergroups, the user will not be able to return to the group
1021
     * on their own using invite links, etc., unless unbanned first.
1022
     * The bot must be an administrator in the group for this to work. Returns True on success.
1023
     *
1024
     * @param int|string $chatId Unique identifier for the target group
1025
     * or username of the target supergroup (in the format @supergroupusername)
1026
     * @param int $userId Unique identifier of the target user
1027
     * @param null|int $untilDate Date when the user will be unbanned, unix time.
1028
     *                            If user is banned for more than 366 days or less than 30 seconds from the current time
1029
     *                            they are considered to be banned forever
1030
     *
1031
     * @return bool
1032
     */
1033
    public function kickChatMember($chatId, $userId, $untilDate = null)
1034
    {
1035
        return $this->call('kickChatMember', [
1036
            'chat_id' => $chatId,
1037
            'user_id' => $userId,
1038
            'until_date' => $untilDate
1039
        ]);
1040
    }
1041
1042
    /**
1043
     * Use this method to unban a previously kicked user in a supergroup.
1044
     * The user will not return to the group automatically, but will be able to join via link, etc.
1045
     * The bot must be an administrator in the group for this to work. Returns True on success.
1046
     *
1047
     * @param int|string $chatId Unique identifier for the target group
1048
     * or username of the target supergroup (in the format @supergroupusername)
1049
     * @param int $userId Unique identifier of the target user
1050
     *
1051
     * @return bool
1052
     */
1053
    public function unbanChatMember($chatId, $userId)
1054
    {
1055
        return $this->call('unbanChatMember', [
1056
            'chat_id' => $chatId,
1057
            'user_id' => $userId,
1058
        ]);
1059
    }
1060
1061
    /**
1062
     * Use this method to send answers to callback queries sent from inline keyboards.
1063
     * The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.
1064
     *
1065
     * @param $callbackQueryId
1066
     * @param null $text
1067
     * @param bool $showAlert
1068
     *
1069
     * @return bool
1070
     */
1071
    public function answerCallbackQuery($callbackQueryId, $text = null, $showAlert = false)
1072
    {
1073
        return $this->call('answerCallbackQuery', [
1074
            'callback_query_id' => $callbackQueryId,
1075
            'text' => $text,
1076
            'show_alert' => (bool)$showAlert,
1077
        ]);
1078
    }
1079
1080
1081
    /**
1082
     * Use this method to edit text messages sent by the bot or via the bot
1083
     *
1084
     * @param int|string $chatId
1085
     * @param int $messageId
1086
     * @param string $text
1087
     * @param string $inlineMessageId
1088
     * @param string|null $parseMode
1089
     * @param bool $disablePreview
1090
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1091
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1092
     * @return Message
1093
     */
1094 View Code Duplication
    public function editMessageText(
1095
        $chatId,
1096
        $messageId,
1097
        $text,
1098
        $parseMode = null,
1099
        $disablePreview = false,
1100
        $replyMarkup = null,
1101
        $inlineMessageId = null
1102
    ) {
1103
        return Message::fromResponse($this->call('editMessageText', [
1104
            'chat_id' => $chatId,
1105
            'message_id' => $messageId,
1106
            'text' => $text,
1107
            'inline_message_id' => $inlineMessageId,
1108
            'parse_mode' => $parseMode,
1109
            'disable_web_page_preview' => $disablePreview,
1110
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1111
        ]));
1112
    }
1113
1114
    /**
1115
     * Use this method to edit text messages sent by the bot or via the bot
1116
     *
1117
     * @param int|string $chatId
1118
     * @param int $messageId
1119
     * @param string|null $caption
1120
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1121
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1122
     * @param string $inlineMessageId
1123
     *
1124
     * @return \TelegramBot\Api\Types\Message
1125
     * @throws \TelegramBot\Api\InvalidArgumentException
1126
     * @throws \TelegramBot\Api\Exception
1127
     */
1128 View Code Duplication
    public function editMessageCaption(
1129
        $chatId,
1130
        $messageId,
1131
        $caption = null,
1132
        $replyMarkup = null,
1133
        $inlineMessageId = null
1134
    ) {
1135
        return Message::fromResponse($this->call('editMessageCaption', [
1136
            'chat_id' => $chatId,
1137
            'message_id' => $messageId,
1138
            'inline_message_id' => $inlineMessageId,
1139
            'caption' => $caption,
1140
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1141
        ]));
1142
    }
1143
1144
    /**
1145
     * Use this method to edit only the reply markup of messages sent by the bot or via the bot
1146
     *
1147
     * @param int|string $chatId
1148
     * @param int $messageId
1149
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1150
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1151
     * @param string $inlineMessageId
1152
     *
1153
     * @return Message
1154
     */
1155 View Code Duplication
    public function editMessageReplyMarkup(
1156
        $chatId,
1157
        $messageId,
1158
        $replyMarkup = null,
1159
        $inlineMessageId = null
1160
    ) {
1161
        return Message::fromResponse($this->call('editMessageReplyMarkup', [
1162
            'chat_id' => $chatId,
1163
            'message_id' => $messageId,
1164
            'inline_message_id' => $inlineMessageId,
1165
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1166
        ]));
1167
    }
1168
1169
    /**
1170
     * Use this method to delete a message, including service messages, with the following limitations:
1171
     *  - A message can only be deleted if it was sent less than 48 hours ago.
1172
     *  - Bots can delete outgoing messages in groups and supergroups.
1173
     *  - Bots granted can_post_messages permissions can delete outgoing messages in channels.
1174
     *  - If the bot is an administrator of a group, it can delete any message there.
1175
     *  - If the bot has can_delete_messages permission in a supergroup or a channel, it can delete any message there.
1176
     *
1177
     * @param int|string $chatId
1178
     * @param int $messageId
1179
     *
1180
     * @return bool
1181
     */
1182
    public function deleteMessage($chatId, $messageId)
1183
    {
1184
        return $this->call('deleteMessage', [
1185
            'chat_id' => $chatId,
1186
            'message_id' => $messageId,
1187
        ]);
1188
    }
1189
1190
    /**
1191
     * Close curl
1192
     */
1193 9
    public function __destruct()
1194
    {
1195 9
        $this->curl && curl_close($this->curl);
1196 9
    }
1197
1198
    /**
1199
     * @return string
1200
     */
1201
    public function getUrl()
1202
    {
1203
        return self::URL_PREFIX.$this->token;
1204
    }
1205
1206
    /**
1207
     * @return string
1208
     */
1209
    public function getFileUrl()
1210
    {
1211
        return self::FILE_URL_PREFIX.$this->token;
1212
    }
1213
1214
    /**
1215
     * @param \TelegramBot\Api\Types\Update $update
1216
     * @param string $eventName
1217
     *
1218
     * @throws \TelegramBot\Api\Exception
1219
     */
1220
    public function trackUpdate(Update $update, $eventName = 'Message')
1221
    {
1222
        if (!in_array($update->getUpdateId(), $this->trackedEvents)) {
1223
            $this->trackedEvents[] = $update->getUpdateId();
1224
1225
            $this->track($update->getMessage(), $eventName);
1226
1227
            if (count($this->trackedEvents) > self::MAX_TRACKED_EVENTS) {
1228
                $this->trackedEvents = array_slice($this->trackedEvents, round(self::MAX_TRACKED_EVENTS / 4));
1229
            }
1230
        }
1231
    }
1232
1233
    /**
1234
     * Wrapper for tracker
1235
     *
1236
     * @param \TelegramBot\Api\Types\Message $message
1237
     * @param string $eventName
1238
     *
1239
     * @throws \TelegramBot\Api\Exception
1240
     */
1241
    public function track(Message $message, $eventName = 'Message')
1242
    {
1243
        if ($this->tracker instanceof Botan) {
1244
            $this->tracker->track($message, $eventName);
1245
        }
1246
    }
1247
1248
    /**
1249
     * Use this method to send invoices. On success, the sent Message is returned.
1250
     *
1251
     * @param int|string $chatId
1252
     * @param string $title
1253
     * @param string $description
1254
     * @param string $payload
1255
     * @param string $providerToken
1256
     * @param string $startParameter
1257
     * @param string $currency
1258
     * @param array $prices
1259
     * @param string|null $photoUrl
1260
     * @param int|null $photoSize
1261
     * @param int|null $photoWidth
1262
     * @param int|null $photoHeight
1263
     * @param bool $needName
1264
     * @param bool $needPhoneNumber
1265
     * @param bool $needEmail
1266
     * @param bool $needShippingAddress
1267
     * @param bool $isFlexible
1268
     * @param int|null $replyToMessageId
1269
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1270
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1271
     * @param bool $disableNotification
1272
     * @param string|null $providerData
1273
     * @param bool $sendPhoneNumberToProvider
1274
     * @param bool $sendEmailToProvider
1275
     *
1276
     * @return Message
1277
     */
1278
    public function sendInvoice(
1279
        $chatId,
1280
        $title,
1281
        $description,
1282
        $payload,
1283
        $providerToken,
1284
        $startParameter,
1285
        $currency,
1286
        $prices,
1287
        $isFlexible = false,
1288
        $photoUrl = null,
1289
        $photoSize = null,
1290
        $photoWidth = null,
1291
        $photoHeight = null,
1292
        $needName = false,
1293
        $needPhoneNumber = false,
1294
        $needEmail = false,
1295
        $needShippingAddress = false,
1296
        $replyToMessageId = null,
1297
        $replyMarkup = null,
1298
        $disableNotification = false,
1299
        $providerData = null,
1300
        $sendPhoneNumberToProvider = false,
1301
        $sendEmailToProvider = false
1302
    ) {
1303
        return Message::fromResponse($this->call('sendInvoice', [
1304
            'chat_id' => $chatId,
1305
            'title' => $title,
1306
            'description' => $description,
1307
            'payload' => $payload,
1308
            'provider_token' => $providerToken,
1309
            'start_parameter' => $startParameter,
1310
            'currency' => $currency,
1311
            'prices' => json_encode($prices),
1312
            'is_flexible' => $isFlexible,
1313
            'photo_url' => $photoUrl,
1314
            'photo_size' => $photoSize,
1315
            'photo_width' => $photoWidth,
1316
            'photo_height' => $photoHeight,
1317
            'need_name' => $needName,
1318
            'need_phone_number' => $needPhoneNumber,
1319
            'need_email' => $needEmail,
1320
            'need_shipping_address' => $needShippingAddress,
1321
            'reply_to_message_id' => $replyToMessageId,
1322
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1323
            'disable_notification' => (bool)$disableNotification,
1324
            'provider_data' => $providerData,
1325
            'send_phone_number_to_provider' => (bool)$sendPhoneNumberToProvider,
1326
            'send_email_to_provider' => (bool)$sendEmailToProvider
1327
        ]));
1328
    }
1329
1330
    /**
1331
     * If you sent an invoice requesting a shipping address and the parameter is_flexible was specified, the Bot API
1332
     * will send an Update with a shipping_query field to the bot. Use this method to reply to shipping queries.
1333
     * On success, True is returned.
1334
     *
1335
     * @param string $shippingQueryId
1336
     * @param bool $ok
1337
     * @param array $shipping_options
1338
     * @param null|string $errorMessage
1339
     *
1340
     * @return bool
1341
     *
1342
     */
1343
    public function answerShippingQuery($shippingQueryId, $ok = true, $shipping_options = [], $errorMessage = null)
1344
    {
1345
        return $this->call('answerShippingQuery', [
1346
            'shipping_query_id' => $shippingQueryId,
1347
            'ok' => (bool)$ok,
1348
            'shipping_options' => json_encode($shipping_options),
1349
            'error_message' => $errorMessage
1350
        ]);
1351
    }
1352
1353
    /**
1354
     * Use this method to respond to such pre-checkout queries. On success, True is returned.
1355
     * Note: The Bot API must receive an answer within 10 seconds after the pre-checkout query was sent.
1356
     *
1357
     * @param string $preCheckoutQueryId
1358
     * @param bool $ok
1359
     * @param null|string $errorMessage
1360
     *
1361
     * @return mixed
1362
     */
1363
    public function answerPreCheckoutQuery($preCheckoutQueryId, $ok = true, $errorMessage = null)
1364
    {
1365
        return $this->call('answerPreCheckoutQuery', [
1366
            'pre_checkout_query_id' => $preCheckoutQueryId,
1367
            'ok' => (bool)$ok,
1368
            'error_message' => $errorMessage
1369
        ]);
1370
    }
1371
1372
    /**
1373
     * Use this method to restrict a user in a supergroup.
1374
     * The bot must be an administrator in the supergroup for this to work and must have the appropriate admin rights.
1375
     * Pass True for all boolean parameters to lift restrictions from a user.
1376
     *
1377
     * @param string|int $chatId Unique identifier for the target chat or username of the target supergroup
1378
     *                   (in the format @supergroupusername)
1379
     * @param int $userId Unique identifier of the target user
1380
     * @param null|integer $untilDate Date when restrictions will be lifted for the user, unix time.
1381
     *                     If user is restricted for more than 366 days or less than 30 seconds from the current time,
1382
     *                     they are considered to be restricted forever
1383
     * @param bool $canSendMessages Pass True, if the user can send text messages, contacts, locations and venues
1384
     * @param bool $canSendMediaMessages No Pass True, if the user can send audios, documents, photos, videos,
1385
     *                                   video notes and voice notes, implies can_send_messages
1386
     * @param bool $canSendOtherMessages Pass True, if the user can send animations, games, stickers and
1387
     *                                   use inline bots, implies can_send_media_messages
1388
     * @param bool $canAddWebPagePreviews Pass True, if the user may add web page previews to their messages,
1389
     *                                    implies can_send_media_messages
1390
     *
1391
     * @return bool
1392
     */
1393
    public function restrictChatMember(
1394
        $chatId,
1395
        $userId,
1396
        $untilDate = null,
1397
        $canSendMessages = false,
1398
        $canSendMediaMessages = false,
1399
        $canSendOtherMessages = false,
1400
        $canAddWebPagePreviews = false
1401
    ) {
1402
        return $this->call('restrictChatMember', [
1403
            'chat_id' => $chatId,
1404
            'user_id' => $userId,
1405
            'until_date' => $untilDate,
1406
            'can_send_messages' => $canSendMessages,
1407
            'can_send_media_messages' => $canSendMediaMessages,
1408
            'can_send_other_messages' => $canSendOtherMessages,
1409
            'can_add_web_page_previews' => $canAddWebPagePreviews
1410
        ]);
1411
    }
1412
1413
    /**
1414
     * Use this method to promote or demote a user in a supergroup or a channel.
1415
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1416
     * Pass False for all boolean parameters to demote a user.
1417
     *
1418
     * @param string|int $chatId Unique identifier for the target chat or username of the target supergroup
1419
     *                   (in the format @supergroupusername)
1420
     * @param int $userId Unique identifier of the target user
1421
     * @param bool $canChangeInfo Pass True, if the administrator can change chat title, photo and other settings
1422
     * @param bool $canPostMessages Pass True, if the administrator can create channel posts, channels only
1423
     * @param bool $canEditMessages Pass True, if the administrator can edit messages of other users, channels only
1424
     * @param bool $canDeleteMessages Pass True, if the administrator can delete messages of other users
1425
     * @param bool $canInviteUsers Pass True, if the administrator can invite new users to the chat
1426
     * @param bool $canRestrictMembers Pass True, if the administrator can restrict, ban or unban chat members
1427
     * @param bool $canPinMessages Pass True, if the administrator can pin messages, supergroups only
1428
     * @param bool $canPromoteMembers Pass True, if the administrator can add new administrators with a subset of his
1429
     *                                own privileges or demote administrators that he has promoted,directly or
1430
     *                                indirectly (promoted by administrators that were appointed by him)
1431
     *
1432
     * @return bool
1433
     */
1434
    public function promoteChatMember(
1435
        $chatId,
1436
        $userId,
1437
        $canChangeInfo = true,
1438
        $canPostMessages = true,
1439
        $canEditMessages = true,
1440
        $canDeleteMessages = true,
1441
        $canInviteUsers = true,
1442
        $canRestrictMembers = true,
1443
        $canPinMessages = true,
1444
        $canPromoteMembers = true
1445
    ) {
1446
        return $this->call('promoteChatMember', [
1447
            'chat_id' => $chatId,
1448
            'user_id' => $userId,
1449
            'can_change_info' => $canChangeInfo,
1450
            'can_post_messages' => $canPostMessages,
1451
            'can_edit_messages' => $canEditMessages,
1452
            'can_delete_messages' => $canDeleteMessages,
1453
            'can_invite_users' => $canInviteUsers,
1454
            'can_restrict_members' => $canRestrictMembers,
1455
            'can_pin_messages' => $canPinMessages,
1456
            'can_promote_members' => $canPromoteMembers
1457
        ]);
1458
    }
1459
1460
    /**
1461
     * Use this method to export an invite link to a supergroup or a channel.
1462
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1463
     *
1464
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1465
     *                           (in the format @channelusername)
1466
     * @return string
1467
     */
1468
    public function exportChatInviteLink($chatId)
1469
    {
1470
        return $this->call('exportChatInviteLink', [
1471
            'chat_id' => $chatId
1472
        ]);
1473
    }
1474
1475
    /**
1476
     * Use this method to set a new profile photo for the chat. Photos can't be changed for private chats.
1477
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1478
     *
1479
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1480
     *                           (in the format @channelusername)
1481
     * @param \CURLFile|string $photo New chat photo, uploaded using multipart/form-data
1482
     *
1483
     * @return bool
1484
     */
1485
    public function setChatPhoto($chatId, $photo)
1486
    {
1487
        return $this->call('setChatPhoto', [
1488
            'chat_id' => $chatId,
1489
            'photo' => $photo
1490
        ]);
1491
    }
1492
1493
    /**
1494
     * Use this method to delete a chat photo. Photos can't be changed for private chats.
1495
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1496
     *
1497
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1498
     *                           (in the format @channelusername)
1499
     *
1500
     * @return bool
1501
     */
1502
    public function deleteChatPhoto($chatId)
1503
    {
1504
        return $this->call('deleteChatPhoto', [
1505
            'chat_id' => $chatId
1506
        ]);
1507
    }
1508
1509
    /**
1510
     * Use this method to change the title of a chat. Titles can't be changed for private chats.
1511
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1512
     *
1513
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1514
     *                           (in the format @channelusername)
1515
     * @param string $title New chat title, 1-255 characters
1516
     *
1517
     * @return bool
1518
     */
1519
    public function setChatTitle($chatId, $title)
1520
    {
1521
        return $this->call('setChatTitle', [
1522
            'chat_id' => $chatId,
1523
            'title' => $title
1524
        ]);
1525
    }
1526
1527
    /**
1528
     * Use this method to change the description of a supergroup or a channel.
1529
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1530
     *
1531
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1532
     *                   (in the format @channelusername)
1533
     * @param string|null $description New chat description, 0-255 characters
1534
     *
1535
     * @return bool
1536
     */
1537
    public function setChatDescription($chatId, $description = null)
1538
    {
1539
        return $this->call('setChatDescription', [
1540
            'chat_id' => $chatId,
1541
            'title' => $description
1542
        ]);
1543
    }
1544
1545
    /**
1546
     * Use this method to pin a message in a supergroup.
1547
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1548
     *
1549
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1550
     *                   (in the format @channelusername)
1551
     * @param int $messageId Identifier of a message to pin
1552
     * @param bool $disableNotification
1553
     *
1554
     * @return bool
1555
     */
1556
    public function pinChatMessage($chatId, $messageId, $disableNotification = false)
1557
    {
1558
        return $this->call('pinChatMessage', [
1559
            'chat_id' => $chatId,
1560
            'message_id' => $messageId,
1561
            'disable_notification' => $disableNotification
1562
        ]);
1563
    }
1564
1565
    /**
1566
     * Use this method to unpin a message in a supergroup chat.
1567
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1568
     *
1569
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1570
     *                   (in the format @channelusername)
1571
     *
1572
     * @return bool
1573
     */
1574
    public function unpinChatMessage($chatId)
1575
    {
1576
        return $this->call('unpinChatMessage', [
1577
            'chat_id' => $chatId
1578
        ]);
1579
    }
1580
1581
    /**
1582
     * Use this method to get up to date information about the chat
1583
     * (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.).
1584
     *
1585
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1586
     *                   (in the format @channelusername)
1587
     *
1588
     * @return Chat
1589
     */
1590
    public function getChat($chatId)
1591
    {
1592
        return Chat::fromResponse($this->call('getChat', [
1593
            'chat_id' => $chatId
1594
        ]));
1595
    }
1596
1597
    /**
1598
     * Use this method to get information about a member of a chat.
1599
     *
1600
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1601
     *                   (in the format @channelusername)
1602
     * @param int $userId
1603
     *
1604
     * @return ChatMember
1605
     */
1606
    public function getChatMember($chatId, $userId)
1607
    {
1608
        return ChatMember::fromResponse($this->call('getChatMember', [
1609
            'chat_id' => $chatId,
1610
            'user_id' => $userId
1611
        ]));
1612
    }
1613
1614
    /**
1615
     * Use this method for your bot to leave a group, supergroup or channel.
1616
     *
1617
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1618
     *                   (in the format @channelusername)
1619
     *
1620
     * @return bool
1621
     */
1622
    public function leaveChat($chatId)
1623
    {
1624
        return $this->call('leaveChat', [
1625
            'chat_id' => $chatId
1626
        ]);
1627
    }
1628
1629
    /**
1630
     * Use this method to get the number of members in a chat.
1631
     *
1632
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1633
     *                   (in the format @channelusername)
1634
     *
1635
     * @return int
1636
     */
1637
    public function getChatMembersCount($chatId)
1638
    {
1639
        return $this->call(
1640
            'getChatMembersCount',
1641
            [
1642
                'chat_id' => $chatId
1643
            ]
1644
        );
1645
    }
1646
1647
    /**
1648
     * Use this method to get a list of administrators in a chat.
1649
     *
1650
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1651
     *                   (in the format @channelusername)
1652
     *
1653
     * @return array
1654
     */
1655
    public function getChatAdministrators($chatId)
1656
    {
1657
        return ArrayOfChatMemberEntity::fromResponse(
1658
            $this->call(
1659
                'getChatAdministrators',
1660
                [
1661
                    'chat_id' => $chatId
1662
                ]
1663
            )
1664
        );
1665
    }
1666
1667
    /**
1668
     * As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1 minute long.
1669
     * Use this method to send video messages.
1670
     * On success, the sent Message is returned.
1671
     *
1672
     * @param int|string $chatId chat_id or @channel_name
1673
     * @param \CURLFile|string $videoNote
1674
     * @param int|null $duration
1675
     * @param int|null $length
1676
     * @param int|null $replyToMessageId
1677
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1678
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1679
     * @param bool $disableNotification
1680
     *
1681
     * @return \TelegramBot\Api\Types\Message
1682
     * @throws \TelegramBot\Api\InvalidArgumentException
1683
     * @throws \TelegramBot\Api\Exception
1684
     */
1685 View Code Duplication
    public function sendVideoNote(
1686
        $chatId,
1687
        $videoNote,
1688
        $duration = null,
1689
        $length = null,
1690
        $replyToMessageId = null,
1691
        $replyMarkup = null,
1692
        $disableNotification = false
1693
    ) {
1694
        return Message::fromResponse($this->call('sendVideoNote', [
1695
            'chat_id' => $chatId,
1696
            'video_note' => $videoNote,
1697
            'duration' => $duration,
1698
            'length' => $length,
1699
            'reply_to_message_id' => $replyToMessageId,
1700
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1701
            'disable_notification' => (bool)$disableNotification
1702
        ]));
1703
    }
1704
1705
    /**
1706
     * Use this method to send a group of photos or videos as an album.
1707
     * On success, the sent \TelegramBot\Api\Types\Message is returned.
1708
     *
1709
     * @param int|string $chatId
1710
     * @param ArrayOfInputMedia $media
1711
     * @param int|null $replyToMessageId
1712
     * @param bool $disableNotification
1713
     *
1714
     * @return array
1715
     * @throws \TelegramBot\Api\Exception
1716
     */
1717
    public function sendMediaGroup(
1718
        $chatId,
1719
        $media,
1720
        $disableNotification = false,
1721
        $replyToMessageId = null
1722
    ) {
1723
        return ArrayOfMessages::fromResponse($this->call('sendMediaGroup', [
1724
            'chat_id' => $chatId,
1725
            'media' => $media->toJson(),
1726
            'reply_to_message_id' => (int)$replyToMessageId,
1727
            'disable_notification' => (bool)$disableNotification
1728
        ]));
1729
    }
1730
1731
    /**
1732
     * Enable proxy for curl requests. Empty string will disable proxy.
1733
     *
1734
     * @param string $proxyString
1735
     *
1736
     * @return BotApi
1737
     */
1738
    public function setProxy($proxyString = '', $socks5 = false)
1739
    {
1740
        if (empty($proxyString)) {
1741
            $this->proxySettings = [];
1742
            return $this;
1743
        }
1744
1745
        $this->proxySettings = [
1746
            CURLOPT_PROXY => $proxyString,
1747
            CURLOPT_HTTPPROXYTUNNEL => true,
1748
        ];
1749
        
1750
        if ($socks5) {
1751
            $this->proxySettings[CURLOPT_PROXYTYPE] = CURLPROXY_SOCKS5;
1752
        }
1753
        return $this;
1754
    }
1755
1756
1757
    /**
1758
     * Use this method to send a native poll. A native poll can't be sent to a private chat.
1759
     * On success, the sent \TelegramBot\Api\Types\Message is returned.
1760
     *
1761
     * @param int|string $chatId
1762
     * @param string $question
1763
     * @param array $options
1764
     * @param bool $disableNotification
1765
     * @param int|null $replyToMessageId
1766
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1767
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1768
     *
1769
     * @return \TelegramBot\Api\Types\Message
1770
     * @throws \TelegramBot\Api\InvalidArgumentException
1771
     * @throws \TelegramBot\Api\Exception
1772
     */
1773 View Code Duplication
    public function sendPoll(
1774
        $chatId,
1775
        $question,
1776
        $options,
1777
        $disableNotification = false,
1778
        $replyToMessageId = null,
1779
        $replyMarkup = null
1780
    ) {
1781
        return Message::fromResponse($this->call('sendPoll', [
1782
            'chat_id' => $chatId,
1783
            'question' => $question,
1784
            'options' => json_encode($options),
1785
            'disable_notification' => (bool)$disableNotification,
1786
            'reply_to_message_id' => (int)$replyToMessageId,
1787
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1788
        ]));
1789
    }
1790
1791
    /**
1792
     * Use this method to stop a poll which was sent by the bot.
1793
     * On success, the stopped \TelegramBot\Api\Types\Poll with the final results is returned.
1794
     *
1795
     * @param int|string $chatId
1796
     * @param int $messageId
1797
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1798
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1799
     * @return Poll
1800
     * @throws \TelegramBot\Api\InvalidArgumentException
1801
     * @throws \TelegramBot\Api\Exception
1802
     */
1803 View Code Duplication
    public function stopPoll(
1804
        $chatId,
1805
        $messageId,
1806
        $replyMarkup = null
1807
    ) {
1808
        return Poll::fromResponse($this->call('stopPoll', [
1809
            'chat_id' => $chatId,
1810
            'message_id' => $messageId,
1811
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1812
        ]));
1813
    }
1814
1815
    /**
1816
     * Set an option for a cURL transfer
1817
     *
1818
     * @param int $option The CURLOPT_XXX option to set
1819
     * @param mixed $value The value to be set on option
1820
     */
1821
    public function setCurlOption($option, $value)
1822
    {
1823
        $this->customCurlOptions[$option] = $value;
1824
    }
1825
1826
    /**
1827
     * Unset an option for a cURL transfer
1828
     *
1829
     * @param int $option The CURLOPT_XXX option to unset
1830
     */
1831
    public function unsetCurlOption($option)
1832
    {
1833
        unset($this->customCurlOptions[$option]);
1834
    }
1835
1836
    /**
1837
     * Clean custom options
1838
     */
1839
    public function resetCurlOptions()
1840
    {
1841
        $this->customCurlOptions = [];
1842
    }
1843
}
1844