Passed
Pull Request — master (#232)
by
unknown
03:26
created

BotApi::sendVenue()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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