Completed
Pull Request — master (#255)
by Eldar
03:12 queued 29s
created

BotApi::sendVoice()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
1841
        ]));
1842
    }
1843
1844
    /**
1845
     * Use this method to send a dice, which will have a random value from 1 to 6.
1846
     * On success, the sent Message is returned. (Yes, we're aware of the “proper” singular of die.
1847
     * But it's awkward, and we decided to help it change. One dice at a time!)
1848
     *
1849
     * @param $chatId string|int Unique identifier for the target chat or username of the target channel
1850
     *                (in the format @channelusername)
1851
     * @param bool $disableNotification Sends the message silently. Users will receive a notification with no sound.
1852
     * @param null $replyToMessageId If the message is a reply, ID of the original message
1853
     * @param null $replyMarkup Additional interface options. A JSON-serialized object for an inline keyboard,
1854
     *                          custom reply keyboard, instructions to remove reply
1855
     *                          keyboard or to force a reply from the user.
1856
     * @return bool|Message
1857
     * @throws Exception
1858
     * @throws HttpException
1859
     * @throws InvalidJsonException
1860
     */
1861 View Code Duplication
    public function sendDice(
1862
        $chatId,
1863
        $disableNotification = false,
1864
        $replyToMessageId = null,
1865
        $replyMarkup = null
1866
    ) {
1867
        return Message::fromResponse($this->call('sendDice', [
1868
            'chat_id' => $chatId,
1869
            'disable_notification' => (bool) $disableNotification,
1870
            'reply_to_message_id' => (int) $replyToMessageId,
1871
            'reply_markup' => $replyMarkup === null ? $replyMarkup : $replyMarkup->toJson(),
0 ignored issues
show
Bug introduced by
The method toJson cannot be called on $replyMarkup (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
1872
        ]));
1873
    }
1874
1875
    /**
1876
     * Use this method to stop a poll which was sent by the bot.
1877
     * On success, the stopped \TelegramBot\Api\Types\Poll with the final results is returned.
1878
     *
1879
     * @param int|string $chatId
1880
     * @param int $messageId
1881
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1882
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1883
     * @return Poll
1884
     * @throws \TelegramBot\Api\InvalidArgumentException
1885
     * @throws \TelegramBot\Api\Exception
1886
     */
1887
    public function stopPoll(
1888
        $chatId,
1889
        $messageId,
1890
        $replyMarkup = null
1891
    ) {
1892
        return Poll::fromResponse($this->call('stopPoll', [
1893
            'chat_id' => $chatId,
1894
            'message_id' => $messageId,
1895
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1896
        ]));
1897
    }
1898
1899
    /**
1900
     * Set an option for a cURL transfer
1901
     *
1902
     * @param int $option The CURLOPT_XXX option to set
1903
     * @param mixed $value The value to be set on option
1904
     */
1905
    public function setCurlOption($option, $value)
1906
    {
1907
        $this->customCurlOptions[$option] = $value;
1908
    }
1909
1910
    /**
1911
     * Unset an option for a cURL transfer
1912
     *
1913
     * @param int $option The CURLOPT_XXX option to unset
1914
     */
1915
    public function unsetCurlOption($option)
1916
    {
1917
        unset($this->customCurlOptions[$option]);
1918
    }
1919
1920
    /**
1921
     * Clean custom options
1922
     */
1923
    public function resetCurlOptions()
1924
    {
1925
        $this->customCurlOptions = [];
1926
    }
1927
}
1928