Test Failed
Pull Request — master (#322)
by Eldar
03:04
created

BotApi::track()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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

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

Loading history...
1945
        ]));
1946
    }
1947
1948
    /**
1949
     * Use this method to send a dice, which will have a random value from 1 to 6.
1950
     * On success, the sent Message is returned. (Yes, we're aware of the “proper” singular of die.
1951
     * But it's awkward, and we decided to help it change. One dice at a time!)
1952
     *
1953
     * @param      $chatId string|int Unique identifier for the target chat or username of the target channel
1954
     *                (in the format @channelusername)
1955
     * @param      $emoji string Emoji on which the dice throw animation is based. Currently, must be one of “🎲”,
1956
     *     “🎯”, “🏀”, “⚽”, or “🎰”. Dice can have values 1-6 for “🎲” and “🎯”, values 1-5 for “🏀” and “⚽”, and
1957
     *     values 1-64 for “🎰”. Defaults to “🎲
1958
     * @param bool $disableNotification Sends the message silently. Users will receive a notification with no sound.
1959
     * @param null $replyToMessageId If the message is a reply, ID of the original message
1960
     * @param bool $$allowSendingWithoutReply Pass True, if the message should be sent even if the specified replied-to
0 ignored issues
show
Documentation introduced by
There is no parameter named $$allowSendingWithoutReply. Did you maybe mean $allowSendingWithoutReply?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
1961
     *     message is not found,
1962
     * @param null $replyMarkup Additional interface options. A JSON-serialized object for an inline keyboard,
1963
     *                          custom reply keyboard, instructions to remove reply
1964
     *                          keyboard or to force a reply from the user.
1965
     *
1966
     * @return bool|Message
1967
     * @throws Exception
1968
     * @throws HttpException
1969
     * @throws InvalidJsonException
1970
     */
1971
    public function sendDice(
1972
        $chatId,
1973
        $emoji,
1974
        $disableNotification = false,
1975
        $replyToMessageId = null,
1976
        $allowSendingWithoutReply = false,
1977
        $replyMarkup = null
1978
    ) {
1979
        return Message::fromResponse($this->call('sendDice', [
1980
            'chat_id' => $chatId,
1981
            'emoji' => $emoji,
1982
            'disable_notification' => (bool) $disableNotification,
1983
            'reply_to_message_id' => (int) $replyToMessageId,
1984
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1985
            'reply_markup' => $replyMarkup === null ? $replyMarkup : $replyMarkup->toJson(),
0 ignored issues
show
Bug introduced by
The method toJson cannot be called on $replyMarkup (of type null).

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

Loading history...
1986
        ]));
1987
    }
1988
1989
    /**
1990
     * Use this method to stop a poll which was sent by the bot.
1991
     * On success, the stopped \TelegramBot\Api\Types\Poll with the final results is returned.
1992
     *
1993
     * @param int|string $chatId
1994
     * @param int $messageId
1995
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1996
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1997
     * @return Poll
1998
     * @throws \TelegramBot\Api\InvalidArgumentException
1999
     * @throws \TelegramBot\Api\Exception
2000
     */
2001
    public function stopPoll(
2002
        $chatId,
2003
        $messageId,
2004
        $replyMarkup = null
2005
    ) {
2006
        return Poll::fromResponse($this->call('stopPoll', [
2007
            'chat_id' => $chatId,
2008
            'message_id' => $messageId,
2009
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
2010
        ]));
2011
    }
2012
2013
    /**
2014
     * Set an option for a cURL transfer
2015
     *
2016
     * @param int $option The CURLOPT_XXX option to set
2017
     * @param mixed $value The value to be set on option
2018
     */
2019
    public function setCurlOption($option, $value)
2020
    {
2021
        $this->customCurlOptions[$option] = $value;
2022
    }
2023
2024
    /**
2025
     * Unset an option for a cURL transfer
2026
     *
2027
     * @param int $option The CURLOPT_XXX option to unset
2028
     */
2029
    public function unsetCurlOption($option)
2030
    {
2031
        unset($this->customCurlOptions[$option]);
2032
    }
2033
2034
    /**
2035
     * Clean custom options
2036
     */
2037
    public function resetCurlOptions()
2038
    {
2039
        $this->customCurlOptions = [];
2040
    }
2041
}
2042