Passed
Pull Request — master (#240)
by
unknown
03:02
created

BotApi::sendInvoice()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 51

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 51
ccs 0
cts 25
cp 0
rs 9.069
c 0
b 0
f 0
cc 2
nc 1
nop 23
crap 6

How to fix   Long Method    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace TelegramBot\Api;
4
5
use TelegramBot\Api\Types\ArrayOfChatMemberEntity;
6
use TelegramBot\Api\Types\ArrayOfMessages;
7
use TelegramBot\Api\Types\ArrayOfUpdates;
8
use TelegramBot\Api\Types\Chat;
9
use TelegramBot\Api\Types\ChatMember;
10
use TelegramBot\Api\Types\File;
11
use TelegramBot\Api\Types\Inline\QueryResult\AbstractInlineQueryResult;
12
use TelegramBot\Api\Types\InputMedia\ArrayOfInputMedia;
13
use TelegramBot\Api\Types\Message;
14
use TelegramBot\Api\Types\Poll;
15
use TelegramBot\Api\Types\Update;
16
use TelegramBot\Api\Types\User;
17
use TelegramBot\Api\Types\UserProfilePhotos;
18
19
/**
20
 * Class BotApi
21
 *
22
 * @package TelegramBot\Api
23
 */
24
class BotApi
25
{
26
    /**
27
     * HTTP codes
28
     *
29
     * @var array
30
     */
31
    public static $codes = [
32
        // Informational 1xx
33
        100 => 'Continue',
34
        101 => 'Switching Protocols',
35
        102 => 'Processing',            // RFC2518
36
        // Success 2xx
37
        200 => 'OK',
38
        201 => 'Created',
39
        202 => 'Accepted',
40
        203 => 'Non-Authoritative Information',
41
        204 => 'No Content',
42
        205 => 'Reset Content',
43
        206 => 'Partial Content',
44
        207 => 'Multi-Status',          // RFC4918
45
        208 => 'Already Reported',      // RFC5842
46
        226 => 'IM Used',               // RFC3229
47
        // Redirection 3xx
48
        300 => 'Multiple Choices',
49
        301 => 'Moved Permanently',
50
        302 => 'Found', // 1.1
51
        303 => 'See Other',
52
        304 => 'Not Modified',
53
        305 => 'Use Proxy',
54
        // 306 is deprecated but reserved
55
        307 => 'Temporary Redirect',
56
        308 => 'Permanent Redirect',    // RFC7238
57
        // Client Error 4xx
58
        400 => 'Bad Request',
59
        401 => 'Unauthorized',
60
        402 => 'Payment Required',
61
        403 => 'Forbidden',
62
        404 => 'Not Found',
63
        405 => 'Method Not Allowed',
64
        406 => 'Not Acceptable',
65
        407 => 'Proxy Authentication Required',
66
        408 => 'Request Timeout',
67
        409 => 'Conflict',
68
        410 => 'Gone',
69
        411 => 'Length Required',
70
        412 => 'Precondition Failed',
71
        413 => 'Payload Too Large',
72
        414 => 'URI Too Long',
73
        415 => 'Unsupported Media Type',
74
        416 => 'Range Not Satisfiable',
75
        417 => 'Expectation Failed',
76
        422 => 'Unprocessable Entity',                                        // RFC4918
77
        423 => 'Locked',                                                      // RFC4918
78
        424 => 'Failed Dependency',                                           // RFC4918
79
        425 => 'Reserved for WebDAV advanced collections expired proposal',   // RFC2817
80
        426 => 'Upgrade Required',                                            // RFC2817
81
        428 => 'Precondition Required',                                       // RFC6585
82
        429 => 'Too Many Requests',                                           // RFC6585
83
        431 => 'Request Header Fields Too Large',                             // RFC6585
84
        // Server Error 5xx
85
        500 => 'Internal Server Error',
86
        501 => 'Not Implemented',
87
        502 => 'Bad Gateway',
88
        503 => 'Service Unavailable',
89
        504 => 'Gateway Timeout',
90
        505 => 'HTTP Version Not Supported',
91
        506 => 'Variant Also Negotiates (Experimental)',                      // RFC2295
92
        507 => 'Insufficient Storage',                                        // RFC4918
93
        508 => 'Loop Detected',                                               // RFC5842
94
        510 => 'Not Extended',                                                // RFC2774
95
        511 => 'Network Authentication Required',                             // RFC6585
96
    ];
97
98
    private $proxySettings = [];
99
100
    /**
101
     * Default http status code
102
     */
103
    const DEFAULT_STATUS_CODE = 200;
104
105
    /**
106
     * Not Modified http status code
107
     */
108
    const NOT_MODIFIED_STATUS_CODE = 304;
109
110
    /**
111
     * Limits for tracked ids
112
     */
113
    const MAX_TRACKED_EVENTS = 200;
114
115
    /**
116
     * Url prefixes
117
     */
118
    const URL_PREFIX = 'https://api.telegram.org/bot';
119
120
    /**
121
     * Url prefix for files
122
     */
123
    const FILE_URL_PREFIX = 'https://api.telegram.org/file/bot';
124
125
    /**
126
     * CURL object
127
     *
128
     * @var
129
     */
130
    protected $curl;
131
132
    /**
133
     * CURL custom options
134
     *
135
     * @var array
136
     */
137
    protected $customCurlOptions = [];
138
139
    /**
140
     * Bot token
141
     *
142
     * @var string
143
     */
144
    protected $token;
145
146
    /**
147
     * Botan tracker
148
     *
149
     * @var \TelegramBot\Api\Botan
150
     */
151
    protected $tracker;
152
153
    /**
154
     * list of event ids
155
     *
156
     * @var array
157
     */
158
    protected $trackedEvents = [];
159
160
    /**
161
     * Check whether return associative array
162
     *
163
     * @var bool
164
     */
165
    protected $returnArray = true;
166
167
    /**
168
     * Constructor
169
     *
170
     * @param string $token Telegram Bot API token
171
     * @param string|null $trackerToken Yandex AppMetrica application api_key
172
     */
173 9
    public function __construct($token, $trackerToken = null)
174
    {
175 9
        $this->curl = curl_init();
176 9
        $this->token = $token;
177
178 9
        if ($trackerToken) {
179
            $this->tracker = new Botan($trackerToken);
180
        }
181 9
    }
182
183
    /**
184
     * Set return array
185
     *
186
     * @param bool $mode
187
     *
188
     * @return $this
189
     */
190
    public function setModeObject($mode = true)
191
    {
192
        $this->returnArray = !$mode;
193
194
        return $this;
195
    }
196
197
198
    /**
199
     * Call method
200
     *
201
     * @param string $method
202
     * @param array|null $data
203
     *
204
     * @return mixed
205
     * @throws \TelegramBot\Api\Exception
206
     * @throws \TelegramBot\Api\HttpException
207
     * @throws \TelegramBot\Api\InvalidJsonException
208
     */
209
    public function call($method, array $data = null)
210
    {
211
        $options = $this->proxySettings + [
212
            CURLOPT_URL => $this->getUrl().'/'.$method,
213
            CURLOPT_RETURNTRANSFER => true,
214
            CURLOPT_POST => null,
215
            CURLOPT_POSTFIELDS => null,
216
            CURLOPT_TIMEOUT => 5,
217
        ];
218
219
        if ($data) {
220
            $options[CURLOPT_POST] = true;
221
            $options[CURLOPT_POSTFIELDS] = $data;
222
        }
223
224
        if (!empty($this->customCurlOptions) && is_array($this->customCurlOptions)) {
225
            $options = $this->customCurlOptions + $options;
226
        }
227
228
        $response = self::jsonValidate($this->executeCurl($options), $this->returnArray);
229
230
        if ($this->returnArray) {
231
            if (!isset($response['ok']) || !$response['ok']) {
232
                throw new Exception($response['description'], $response['error_code']);
233
            }
234
235
            return $response['result'];
236
        }
237
238
        if (!$response->ok) {
239
            throw new Exception($response->description, $response->error_code);
240
        }
241
242
        return $response->result;
243
    }
244
245
    /**
246
     * curl_exec wrapper for response validation
247
     *
248
     * @param array $options
249
     *
250
     * @return string
251
     *
252
     * @throws \TelegramBot\Api\HttpException
253
     */
254
    protected function executeCurl(array $options)
255
    {
256
        curl_setopt_array($this->curl, $options);
257
258
        $result = curl_exec($this->curl);
259
        self::curlValidate($this->curl, $result);
260
        if ($result === false) {
261
            throw new HttpException(curl_error($this->curl), curl_errno($this->curl));
262
        }
263
264
        return $result;
265
    }
266
267
    /**
268
     * Response validation
269
     *
270
     * @param resource $curl
271
     * @param string $response
272
     * @throws HttpException
273
     */
274
    public static function curlValidate($curl, $response = null)
275
    {
276
        $json = json_decode($response, true)?: [];
277
        if (($httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE))
278
            && !in_array($httpCode, [self::DEFAULT_STATUS_CODE, self::NOT_MODIFIED_STATUS_CODE])
279
        ) {
280
            $errorDescription = array_key_exists('description', $json) ? $json['description'] : self::$codes[$httpCode];
281
            $errorParameters = array_key_exists('parameters', $json) ? $json['parameters'] : [];
282
            throw new HttpException($errorDescription, $httpCode, null, $errorParameters);
283
        }
284
    }
285
286
    /**
287
     * JSON validation
288
     *
289
     * @param string $jsonString
290
     * @param boolean $asArray
291
     *
292
     * @return object|array
293
     * @throws \TelegramBot\Api\InvalidJsonException
294
     */
295
    public static function jsonValidate($jsonString, $asArray)
296
    {
297
        try {
298
            $json = json_decode($jsonString, $asArray);
299
300
            return $json;
301
        } catch (\Throwable $th) {
302
            if (json_last_error() != JSON_ERROR_NONE) {
303
                throw new InvalidJsonException(json_last_error_msg(), json_last_error());
304
            }
305
        }
306
    }
307
308
    /**
309
     * Use this method to send text messages. On success, the sent \TelegramBot\Api\Types\Message is returned.
310
     *
311
     * @param int|string $chatId
312
     * @param string $text
313
     * @param string|null $parseMode
314
     * @param bool $disablePreview
315
     * @param int|null $replyToMessageId
316
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
317
     *        Types\ReplyKeyboardRemove|null $replyMarkup
318
     * @param bool $disableNotification
319
     *
320
     * @return \TelegramBot\Api\Types\Message
321
     * @throws \TelegramBot\Api\InvalidArgumentException
322
     * @throws \TelegramBot\Api\Exception
323
     */
324
    public function sendMessage(
325
        $chatId,
326
        $text,
327
        $parseMode = null,
328
        $disablePreview = false,
329
        $replyToMessageId = null,
330
        $replyMarkup = null,
331
        $disableNotification = false
332
    ) {
333
        return Message::fromResponse($this->call('sendMessage', [
334
            'chat_id' => $chatId,
335
            'text' => $text,
336
            'parse_mode' => $parseMode,
337
            'disable_web_page_preview' => $disablePreview,
338
            'reply_to_message_id' => (int)$replyToMessageId,
339
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
340
            'disable_notification' => (bool)$disableNotification,
341
        ]));
342
    }
343
344
    /**
345
     * Use this method to send phone contacts
346
     *
347
     * @param int|string $chatId chat_id or @channel_name
348
     * @param string $phoneNumber
349
     * @param string $firstName
350
     * @param string $lastName
351
     * @param int|null $replyToMessageId
352
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
353
     *        Types\ReplyKeyboardRemove|null $replyMarkup
354
     * @param bool $disableNotification
355
     *
356
     * @return \TelegramBot\Api\Types\Message
357
     * @throws \TelegramBot\Api\Exception
358
     */
359
    public function sendContact(
360
        $chatId,
361
        $phoneNumber,
362
        $firstName,
363
        $lastName = null,
364
        $replyToMessageId = null,
365
        $replyMarkup = null,
366
        $disableNotification = false
367
    ) {
368
        return Message::fromResponse($this->call('sendContact', [
369
            'chat_id' => $chatId,
370
            'phone_number' => $phoneNumber,
371
            'first_name' => $firstName,
372
            'last_name' => $lastName,
373
            'reply_to_message_id' => $replyToMessageId,
374
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
375
            'disable_notification' => (bool)$disableNotification,
376
        ]));
377
    }
378
379
    /**
380
     * Use this method when you need to tell the user that something is happening on the bot's side.
381
     * The status is set for 5 seconds or less (when a message arrives from your bot,
382
     * Telegram clients clear its typing status).
383
     *
384
     * We only recommend using this method when a response from the bot will take a noticeable amount of time to arrive.
385
     *
386
     * Type of action to broadcast. Choose one, depending on what the user is about to receive:
387
     * `typing` for text messages, `upload_photo` for photos, `record_video` or `upload_video` for videos,
388
     * `record_audio` or upload_audio for audio files, `upload_document` for general files,
389
     * `find_location` for location data.
390
     *
391
     * @param int $chatId
392
     * @param string $action
393
     *
394
     * @return bool
395
     * @throws \TelegramBot\Api\Exception
396
     */
397
    public function sendChatAction($chatId, $action)
398
    {
399
        return $this->call('sendChatAction', [
400
            'chat_id' => $chatId,
401
            'action' => $action,
402
        ]);
403
    }
404
405
    /**
406
     * Use this method to get a list of profile pictures for a user.
407
     *
408
     * @param int $userId
409
     * @param int $offset
410
     * @param int $limit
411
     *
412
     * @return \TelegramBot\Api\Types\UserProfilePhotos
413
     * @throws \TelegramBot\Api\Exception
414
     */
415
    public function getUserProfilePhotos($userId, $offset = 0, $limit = 100)
416
    {
417
        return UserProfilePhotos::fromResponse($this->call('getUserProfilePhotos', [
418
            'user_id' => (int)$userId,
419
            'offset' => (int)$offset,
420
            'limit' => (int)$limit,
421
        ]));
422
    }
423
424
    /**
425
     * Use this method to specify a url and receive incoming updates via an outgoing webhook.
426
     * Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url,
427
     * containing a JSON-serialized Update.
428
     * In case of an unsuccessful request, we will give up after a reasonable amount of attempts.
429
     *
430
     * @param string $url HTTPS url to send updates to. Use an empty string to remove webhook integration
431
     * @param \CURLFile|string $certificate Upload your public key certificate
432
     *                                      so that the root certificate in use can be checked
433
     *
434
     * @return string
435
     *
436
     * @throws \TelegramBot\Api\Exception
437
     */
438
    public function setWebhook($url = '', $certificate = null)
439
    {
440
        return $this->call('setWebhook', ['url' => $url, 'certificate' => $certificate]);
441
    }
442
    
443
    
444
    /**
445
     * Use this method to clear webhook and use getUpdates again!
446
     *
447
     * @return mixed
448
     *
449
     * @throws \TelegramBot\Api\Exception
450
     */
451
    public function deleteWebhook()
452
    {
453
        return $this->call('deleteWebhook');
454
    }
455
456
    /**
457
     * A simple method for testing your bot's auth token.Requires no parameters.
458
     * Returns basic information about the bot in form of a User object.
459
     *
460
     * @return \TelegramBot\Api\Types\User
461
     * @throws \TelegramBot\Api\Exception
462
     * @throws \TelegramBot\Api\InvalidArgumentException
463
     */
464
    public function getMe()
465
    {
466
        return User::fromResponse($this->call('getMe'));
467
    }
468
469
    /**
470
     * Use this method to receive incoming updates using long polling.
471
     * An Array of Update objects is returned.
472
     *
473
     * Notes
474
     * 1. This method will not work if an outgoing webhook is set up.
475
     * 2. In order to avoid getting duplicate updates, recalculate offset after each server response.
476
     *
477
     * @param int $offset
478
     * @param int $limit
479
     * @param int $timeout
480
     *
481
     * @return Update[]
482
     * @throws \TelegramBot\Api\Exception
483
     * @throws \TelegramBot\Api\InvalidArgumentException
484
     */
485 2
    public function getUpdates($offset = 0, $limit = 100, $timeout = 0)
486
    {
487 2
        $updates = ArrayOfUpdates::fromResponse($this->call('getUpdates', [
488 2
            'offset' => $offset,
489 2
            'limit' => $limit,
490 2
            'timeout' => $timeout,
491 2
        ]));
492
493 2
        if ($this->tracker instanceof Botan) {
494
            foreach ($updates as $update) {
495
                $this->trackUpdate($update);
496
            }
497
        }
498
499 2
        return $updates;
500
    }
501
502
    /**
503
     * Use this method to send point on the map. On success, the sent Message is returned.
504
     *
505
     * @param int|string                                                              $chatId
506
     * @param float                                                                   $latitude
507
     * @param float                                                                   $longitude
508
     * @param int|null                                                                $replyToMessageId
509
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
510
     *        Types\ReplyKeyboardRemove|null $replyMarkup
511
     * @param bool                                                                    $disableNotification
512
     *
513
     * @param null|int                                                                $livePeriod
514
     * @return \TelegramBot\Api\Types\Message
515
     */
516
    public function sendLocation(
517
        $chatId,
518
        $latitude,
519
        $longitude,
520
        $replyToMessageId = null,
521
        $replyMarkup = null,
522
        $disableNotification = false,
523
        $livePeriod = null
524
    ) {
525
        return Message::fromResponse($this->call('sendLocation', [
526
            'chat_id'              => $chatId,
527
            'latitude'             => $latitude,
528
            'longitude'            => $longitude,
529
            'live_period'          => $livePeriod,
530
            'reply_to_message_id'  => $replyToMessageId,
531
            'reply_markup'         => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
532
            'disable_notification' => (bool)$disableNotification,
533
        ]));
534
    }
535
536
    /**
537
     * Use this method to edit live location messages sent by the bot or via the bot (for inline bots).
538
     *
539
     * @param int|string                                                              $chatId
540
     * @param int                                                                     $messageId
541
     * @param string                                                                  $inlineMessageId
542
     * @param float                                                                   $latitude
543
     * @param float                                                                   $longitude
544
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
545
     *        Types\ReplyKeyboardRemove|null $replyMarkup
546
     * @return \TelegramBot\Api\Types\Message
547
     */
548
    public function editMessageLiveLocation(
549
        $chatId,
550
        $messageId,
551
        $inlineMessageId,
552
        $latitude,
553
        $longitude,
554
        $replyMarkup = null
555
    ) {
556
        return Message::fromResponse($this->call('sendLocation', [
557
            'chat_id'           => $chatId,
558
            'message_id'        => $messageId,
559
            'inline_message_id' => $inlineMessageId,
560
            'latitude'          => $latitude,
561
            'longitude'         => $longitude,
562
            'reply_markup'      => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
563
        ]));
564
    }
565
566
    /**
567
     * Use this method to stop updating a live location message sent by the bot or via the bot (for inline bots) before
568
     * live_period expires.
569
     *
570
     * @param int|string                                                              $chatId
571
     * @param int                                                                     $messageId
572
     * @param string                                                                  $inlineMessageId
573
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
574
     *        Types\ReplyKeyboardRemove|null $replyMarkup
575
     * @return \TelegramBot\Api\Types\Message
576
     */
577
    public function stopMessageLiveLocation(
578
        $chatId,
579
        $messageId,
580
        $inlineMessageId,
581
        $replyMarkup = null
582
    ) {
583
        return Message::fromResponse($this->call('sendLocation', [
584
            'chat_id'           => $chatId,
585
            'message_id'        => $messageId,
586
            'inline_message_id' => $inlineMessageId,
587
            'reply_markup'      => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
588
        ]));
589
    }
590
591
    /**
592
     * Use this method to send information about a venue. On success, the sent Message is returned.
593
     *
594
     * @param int|string $chatId chat_id or @channel_name
595
     * @param float $latitude
596
     * @param float $longitude
597
     * @param string $title
598
     * @param string $address
599
     * @param string|null $foursquareId
600
     * @param int|null $replyToMessageId
601
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
602
     *        Types\ReplyKeyboardRemove|null $replyMarkup
603
     * @param bool $disableNotification
604
     *
605
     * @return \TelegramBot\Api\Types\Message
606
     * @throws \TelegramBot\Api\Exception
607
     */
608
    public function sendVenue(
609
        $chatId,
610
        $latitude,
611
        $longitude,
612
        $title,
613
        $address,
614
        $foursquareId = null,
615
        $replyToMessageId = null,
616
        $replyMarkup = null,
617
        $disableNotification = false
618
    ) {
619
        return Message::fromResponse($this->call('sendVenue', [
620
            'chat_id' => $chatId,
621
            'latitude' => $latitude,
622
            'longitude' => $longitude,
623
            'title' => $title,
624
            'address' => $address,
625
            'foursquare_id' => $foursquareId,
626
            'reply_to_message_id' => $replyToMessageId,
627
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
628
            'disable_notification' => (bool)$disableNotification,
629
        ]));
630
    }
631
632
    /**
633
     * Use this method to send .webp stickers. On success, the sent Message is returned.
634
     *
635
     * @param int|string $chatId chat_id or @channel_name
636
     * @param \CURLFile|string $sticker
637
     * @param int|null $replyToMessageId
638
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
639
     *        Types\ReplyKeyboardRemove|null $replyMarkup
640
     * @param bool $disableNotification
641
     *
642
     * @return \TelegramBot\Api\Types\Message
643
     * @throws \TelegramBot\Api\InvalidArgumentException
644
     * @throws \TelegramBot\Api\Exception
645
     */
646 View Code Duplication
    public function sendSticker(
647
        $chatId,
648
        $sticker,
649
        $replyToMessageId = null,
650
        $replyMarkup = null,
651
        $disableNotification = false
652
    ) {
653
        return Message::fromResponse($this->call('sendSticker', [
654
            'chat_id' => $chatId,
655
            'sticker' => $sticker,
656
            'reply_to_message_id' => $replyToMessageId,
657
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
658
            'disable_notification' => (bool)$disableNotification,
659
        ]));
660
    }
661
662
    /**
663
     * Use this method to send video files,
664
     * Telegram clients support mp4 videos (other formats may be sent as Document).
665
     * On success, the sent Message is returned.
666
     *
667
     * @param int|string $chatId chat_id or @channel_name
668
     * @param \CURLFile|string $video
669
     * @param int|null $duration
670
     * @param string|null $caption
671
     * @param int|null $replyToMessageId
672
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
673
     *        Types\ReplyKeyboardRemove|null $replyMarkup
674
     * @param bool $disableNotification
675
     * @param bool $supportsStreaming Pass True, if the uploaded video is suitable for streaming
676
     * @param string|null $parseMode
677
     *
678
     * @return \TelegramBot\Api\Types\Message
679
     * @throws \TelegramBot\Api\InvalidArgumentException
680
     * @throws \TelegramBot\Api\Exception
681
     */
682 View Code Duplication
    public function sendVideo(
683
        $chatId,
684
        $video,
685
        $duration = null,
686
        $caption = null,
687
        $replyToMessageId = null,
688
        $replyMarkup = null,
689
        $disableNotification = false,
690
        $supportsStreaming = false,
691
        $parseMode = null
692
    ) {
693
        return Message::fromResponse($this->call('sendVideo', [
694
            'chat_id' => $chatId,
695
            'video' => $video,
696
            'duration' => $duration,
697
            'caption' => $caption,
698
            'reply_to_message_id' => $replyToMessageId,
699
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
700
            'disable_notification' => (bool)$disableNotification,
701
            'supports_streaming' => (bool)$supportsStreaming,
702
            'parse_mode' => $parseMode
703
        ]));
704
    }
705
706
    /**
707
     * Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound),
708
     * On success, the sent Message is returned.
709
     * Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future.
710
     *
711
     * @param int|string $chatId chat_id or @channel_name
712
     * @param \CURLFile|string $animation
713
     * @param int|null $duration
714
     * @param string|null $caption
715
     * @param int|null $replyToMessageId
716
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
717
     *        Types\ReplyKeyboardRemove|null $replyMarkup
718
     * @param bool $disableNotification
719
     * @param string|null $parseMode
720
     *
721
     * @return \TelegramBot\Api\Types\Message
722
     * @throws \TelegramBot\Api\InvalidArgumentException
723
     * @throws \TelegramBot\Api\Exception
724
     */
725 View Code Duplication
    public function sendAnimation(
726
        $chatId,
727
        $animation,
728
        $duration = null,
729
        $caption = null,
730
        $replyToMessageId = null,
731
        $replyMarkup = null,
732
        $disableNotification = false,
733
        $parseMode = null
734
    ) {
735
        return Message::fromResponse($this->call('sendAnimation', [
736
            'chat_id' => $chatId,
737
            'animation' => $animation,
738
            'duration' => $duration,
739
            'caption' => $caption,
740
            'reply_to_message_id' => $replyToMessageId,
741
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
742
            'disable_notification' => (bool)$disableNotification,
743
            'parse_mode' => $parseMode
744
        ]));
745
    }
746
747
    /**
748
     * Use this method to send audio files,
749
     * if you want Telegram clients to display the file as a playable voice message.
750
     * For this to work, your audio must be in an .ogg file encoded with OPUS
751
     * (other formats may be sent as Audio or Document).
752
     * On success, the sent Message is returned.
753
     * Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future.
754
     *
755
     * @param int|string $chatId chat_id or @channel_name
756
     * @param \CURLFile|string $voice
757
     * @param int|null $duration
758
     * @param int|null $replyToMessageId
759
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
760
     *        Types\ReplyKeyboardRemove|null $replyMarkup
761
     * @param bool $disableNotification
762
     * @param string|null $parseMode
763
     *
764
     * @return \TelegramBot\Api\Types\Message
765
     * @throws \TelegramBot\Api\InvalidArgumentException
766
     * @throws \TelegramBot\Api\Exception
767
     */
768
    public function sendVoice(
769
        $chatId,
770
        $voice,
771
        $duration = null,
772
        $replyToMessageId = null,
773
        $replyMarkup = null,
774
        $disableNotification = false,
775
        $parseMode = null
776
    ) {
777
        return Message::fromResponse($this->call('sendVoice', [
778
            'chat_id' => $chatId,
779
            'voice' => $voice,
780
            'duration' => $duration,
781
            'reply_to_message_id' => $replyToMessageId,
782
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
783
            'disable_notification' => (bool)$disableNotification,
784
            'parse_mode' => $parseMode
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
    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
    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
    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
    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
    /**
1760
     * Use this method to send a native poll. A native poll can't be sent to a private chat.
1761
     * On success, the sent \TelegramBot\Api\Types\Message is returned.
1762
     *
1763
     * @param int|string $chatId
1764
     * @param string $question
1765
     * @param array $options
1766
     * @param bool $disableNotification
1767
     * @param int|null $replyToMessageId
1768
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1769
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1770
     *
1771
     * @return \TelegramBot\Api\Types\Message
1772
     * @throws \TelegramBot\Api\InvalidArgumentException
1773
     * @throws \TelegramBot\Api\Exception
1774
     */
1775 View Code Duplication
    public function sendPoll(
1776
        $chatId,
1777
        $question,
1778
        $options,
1779
        $disableNotification = false,
1780
        $replyToMessageId = null,
1781
        $replyMarkup = null
1782
    ) {
1783
        return Message::fromResponse($this->call('sendPoll', [
1784
            'chat_id' => $chatId,
1785
            'question' => $question,
1786
            'options' => json_encode($options),
1787
            'disable_notification' => (bool)$disableNotification,
1788
            'reply_to_message_id' => (int)$replyToMessageId,
1789
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1790
        ]));
1791
    }
1792
1793
    /**
1794
     * Use this method to stop a poll which was sent by the bot.
1795
     * On success, the stopped \TelegramBot\Api\Types\Poll with the final results is returned.
1796
     *
1797
     * @param int|string $chatId
1798
     * @param int $messageId
1799
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1800
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1801
     * @return Poll
1802
     * @throws \TelegramBot\Api\InvalidArgumentException
1803
     * @throws \TelegramBot\Api\Exception
1804
     */
1805
    public function stopPoll(
1806
        $chatId,
1807
        $messageId,
1808
        $replyMarkup = null
1809
    ) {
1810
        return Poll::fromResponse($this->call('stopPoll', [
1811
            'chat_id' => $chatId,
1812
            'message_id' => $messageId,
1813
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1814
        ]));
1815
    }
1816
1817
    /**
1818
     * Set an option for a cURL transfer
1819
     *
1820
     * @param int $option The CURLOPT_XXX option to set
1821
     * @param mixed $value The value to be set on option
1822
     */
1823
    public function setCurlOption($option, $value)
1824
    {
1825
        $this->customCurlOptions[$option] = $value;
1826
    }
1827
1828
    /**
1829
     * Unset an option for a cURL transfer
1830
     *
1831
     * @param int $option The CURLOPT_XXX option to unset
1832
     */
1833
    public function unsetCurlOption($option)
1834
    {
1835
        unset($this->customCurlOptions[$option]);
1836
    }
1837
1838
    /**
1839
     * Clean custom options
1840
     */
1841
    public function resetCurlOptions()
1842
    {
1843
        $this->customCurlOptions = [];
1844
    }
1845
}
1846