Passed
Pull Request — master (#146)
by
unknown
03:06
created

BotApi   F

Complexity

Total Complexity 100

Size/Duplication

Total Lines 1703
Duplicated Lines 13.39 %

Coupling/Cohesion

Components 1
Dependencies 15

Test Coverage

Coverage 3.83%

Importance

Changes 0
Metric Value
wmc 100
lcom 1
cbo 15
dl 228
loc 1703
ccs 16
cts 418
cp 0.0383
rs 0.6314
c 0
b 0
f 0

62 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 2
A setModeObject() 0 6 1
C call() 0 35 7
A executeCurl() 0 12 2
B curlValidate() 0 11 6
A jsonValidate() 0 10 2
A sendMessage() 19 19 2
A sendContact() 19 19 2
A sendChatAction() 0 7 1
A getUserProfilePhotos() 0 8 1
A setWebhook() 0 4 1
A getMe() 0 4 1
A getUpdates() 0 16 3
A sendLocation() 19 19 2
A editMessageLiveLocation() 0 17 2
A stopMessageLiveLocation() 0 13 2
A sendVenue() 0 23 2
A sendSticker() 15 15 2
A sendVideo() 23 23 2
A sendVoice() 19 19 2
A forwardMessage() 0 9 1
A sendAudio() 23 23 2
A sendPhoto() 19 19 2
A sendDocument() 19 19 2
A getFile() 0 4 1
A downloadFile() 0 12 1
B answerInlineQuery() 0 24 1
A kickChatMember() 0 8 1
A unbanChatMember() 0 7 1
A answerCallbackQuery() 0 8 1
A editMessageText() 19 19 2
A editMessageCaption() 15 15 2
A editMessageReplyMarkup() 0 13 2
A deleteMessage() 0 7 1
A __destruct() 0 4 2
A getUrl() 0 4 1
A getFileUrl() 0 4 1
A trackUpdate() 0 12 3
A track() 0 6 2
A sendInvoice() 0 51 2
A answerShippingQuery() 0 9 1
A answerPreCheckoutQuery() 0 8 1
A restrictChatMember() 0 19 1
B promoteChatMember() 0 25 1
A exportChatInviteLink() 0 6 1
A setChatPhoto() 0 7 1
A deleteChatPhoto() 0 6 1
A setChatTitle() 0 7 1
A setChatDescription() 0 7 1
A pinChatMessage() 0 8 1
A unpinChatMessage() 0 6 1
A getChat() 0 6 1
A getChatMember() 0 7 1
A leaveChat() 0 6 1
A getChatMembersCount() 0 9 1
A getChatAdministrators() 0 11 1
A sendVideoNote() 19 19 2
A sendMediaGroup() 0 13 1
A setProxy() 0 13 2
A setCurlOption() 0 4 1
A unsetCurlOption() 0 4 1
A resetCurlOptions() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like BotApi often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use BotApi, and based on these observations, apply Extract Interface, too.

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