Passed
Pull Request — master (#439)
by Alexander
01:42
created

BotApi::banChatMember()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 7
ccs 0
cts 1
cp 0
rs 10
cc 1
nc 1
nop 4
crap 2
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\ArrayOfSticker;
10
use TelegramBot\Api\Types\ArrayOfUpdates;
11
use TelegramBot\Api\Types\BotCommand;
12
use TelegramBot\Api\Types\Chat;
13
use TelegramBot\Api\Types\ChatMember;
14
use TelegramBot\Api\Types\File;
15
use TelegramBot\Api\Types\ForceReply;
16
use TelegramBot\Api\Types\ForumTopic;
17
use TelegramBot\Api\Types\Inline\InlineKeyboardMarkup;
18
use TelegramBot\Api\Types\Inline\QueryResult\AbstractInlineQueryResult;
19
use TelegramBot\Api\Types\InputMedia\ArrayOfInputMedia;
20
use TelegramBot\Api\Types\InputMedia\InputMedia;
21
use TelegramBot\Api\Types\MaskPosition;
22
use TelegramBot\Api\Types\Message;
23
use TelegramBot\Api\Types\MessageId;
24
use TelegramBot\Api\Types\Poll;
25
use TelegramBot\Api\Types\ReplyKeyboardMarkup;
26
use TelegramBot\Api\Types\ReplyKeyboardRemove;
27
use TelegramBot\Api\Types\SentWebAppMessage;
28
use TelegramBot\Api\Types\Sticker;
29
use TelegramBot\Api\Types\StickerSet;
30
use TelegramBot\Api\Types\Update;
31
use TelegramBot\Api\Types\User;
32
use TelegramBot\Api\Types\UserProfilePhotos;
33
use TelegramBot\Api\Types\WebhookInfo;
34
35
/**
36
 * Class BotApi
37
 *
38
 * @package TelegramBot\Api
39
 */
40
class BotApi
41
{
42
    /**
43
     * HTTP codes
44
     *
45
     * @var array
46
     */
47
    public static $codes = [
48
        // Informational 1xx
49
        100 => 'Continue',
50
        101 => 'Switching Protocols',
51
        102 => 'Processing',            // RFC2518
52
        // Success 2xx
53
        200 => 'OK',
54
        201 => 'Created',
55
        202 => 'Accepted',
56
        203 => 'Non-Authoritative Information',
57
        204 => 'No Content',
58
        205 => 'Reset Content',
59
        206 => 'Partial Content',
60
        207 => 'Multi-Status',          // RFC4918
61
        208 => 'Already Reported',      // RFC5842
62
        226 => 'IM Used',               // RFC3229
63
        // Redirection 3xx
64
        300 => 'Multiple Choices',
65
        301 => 'Moved Permanently',
66
        302 => 'Found', // 1.1
67
        303 => 'See Other',
68
        304 => 'Not Modified',
69
        305 => 'Use Proxy',
70
        // 306 is deprecated but reserved
71
        307 => 'Temporary Redirect',
72
        308 => 'Permanent Redirect',    // RFC7238
73
        // Client Error 4xx
74
        400 => 'Bad Request',
75
        401 => 'Unauthorized',
76
        402 => 'Payment Required',
77
        403 => 'Forbidden',
78
        404 => 'Not Found',
79
        405 => 'Method Not Allowed',
80
        406 => 'Not Acceptable',
81
        407 => 'Proxy Authentication Required',
82
        408 => 'Request Timeout',
83
        409 => 'Conflict',
84
        410 => 'Gone',
85
        411 => 'Length Required',
86
        412 => 'Precondition Failed',
87
        413 => 'Payload Too Large',
88
        414 => 'URI Too Long',
89
        415 => 'Unsupported Media Type',
90
        416 => 'Range Not Satisfiable',
91
        417 => 'Expectation Failed',
92
        422 => 'Unprocessable Entity',                                        // RFC4918
93
        423 => 'Locked',                                                      // RFC4918
94
        424 => 'Failed Dependency',                                           // RFC4918
95
        425 => 'Reserved for WebDAV advanced collections expired proposal',   // RFC2817
96
        426 => 'Upgrade Required',                                            // RFC2817
97
        428 => 'Precondition Required',                                       // RFC6585
98
        429 => 'Too Many Requests',                                           // RFC6585
99
        431 => 'Request Header Fields Too Large',                             // RFC6585
100
        // Server Error 5xx
101
        500 => 'Internal Server Error',
102
        501 => 'Not Implemented',
103
        502 => 'Bad Gateway',
104
        503 => 'Service Unavailable',
105
        504 => 'Gateway Timeout',
106
        505 => 'HTTP Version Not Supported',
107
        506 => 'Variant Also Negotiates (Experimental)',                      // RFC2295
108
        507 => 'Insufficient Storage',                                        // RFC4918
109
        508 => 'Loop Detected',                                               // RFC5842
110
        510 => 'Not Extended',                                                // RFC2774
111
        511 => 'Network Authentication Required',                             // RFC6585
112
    ];
113
114
    /**
115
     * @var array
116
     */
117
    private $proxySettings = [];
118
119
    /**
120
     * Default http status code
121
     */
122
    const DEFAULT_STATUS_CODE = 200;
123
124
    /**
125
     * Not Modified http status code
126
     */
127
    const NOT_MODIFIED_STATUS_CODE = 304;
128
129
    /**
130
     * Limits for tracked ids
131
     */
132
    const MAX_TRACKED_EVENTS = 200;
133
134
    /**
135
     * Url prefixes
136
     */
137
    const URL_PREFIX = 'https://api.telegram.org/bot';
138
139
    /**
140
     * Url prefix for files
141
     */
142
    const FILE_URL_PREFIX = 'https://api.telegram.org/file/bot';
143
144
    /**
145
     * CURL object
146
     *
147
     * @var resource
148
     */
149
    protected $curl;
150
151
    /**
152
     * CURL custom options
153
     *
154
     * @var array
155
     */
156
    protected $customCurlOptions = [];
157
158
    /**
159
     * Bot token
160
     *
161
     * @var string
162
     */
163
    protected $token;
164
165
    /**
166
     * Botan tracker
167
     *
168
     * @var Botan|null
169
     */
170
    protected $tracker;
171
172
    /**
173
     * list of event ids
174
     *
175
     * @var array
176
     */
177
    protected $trackedEvents = [];
178
179
    /**
180
     * Check whether return associative array
181
     *
182
     * @var bool
183
     */
184
    protected $returnArray = true;
185
186
    /**
187
     * Constructor
188 9
     *
189
     * @param string $token Telegram Bot API token
190 9
     * @param string|null $trackerToken Yandex AppMetrica application api_key
191 9
     * @throws \Exception
192
     */
193 9
    public function __construct($token, $trackerToken = null)
194
    {
195
        $this->curl = curl_init();
0 ignored issues
show
Documentation Bug introduced by
It seems like curl_init() can also be of type CurlHandle. However, the property $curl is declared as type resource. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
196 9
        $this->token = $token;
197
198
        if ($trackerToken) {
199
            @trigger_error(sprintf('Passing $trackerToken to %s is deprecated', self::class), \E_USER_DEPRECATED);
200
            $this->tracker = new Botan($trackerToken);
0 ignored issues
show
Deprecated Code introduced by
The class TelegramBot\Api\Botan has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

200
            $this->tracker = /** @scrutinizer ignore-deprecated */ new Botan($trackerToken);
Loading history...
201
        }
202
    }
203
204
    /**
205
     * Set return array
206
     *
207
     * @param bool $mode
208
     *
209
     * @return $this
210
     */
211
    public function setModeObject($mode = true)
212
    {
213
        $this->returnArray = !$mode;
214
215
        return $this;
216
    }
217
218
    /**
219
     * Call method
220
     *
221
     * @param string $method
222
     * @param array|null $data
223
     * @param int $timeout
224
     *
225
     * @return mixed
226
     * @throws Exception
227
     * @throws HttpException
228
     * @throws InvalidJsonException
229
     */
230
    public function call($method, array $data = null, $timeout = 10)
231
    {
232
        $options = $this->proxySettings + [
233
            CURLOPT_URL => $this->getUrl().'/'.$method,
234
            CURLOPT_RETURNTRANSFER => true,
235
            CURLOPT_POST => null,
236
            CURLOPT_POSTFIELDS => null,
237
            CURLOPT_TIMEOUT => $timeout,
238
        ];
239
240
        if ($data) {
241
            $options[CURLOPT_POST] = true;
242
            $options[CURLOPT_POSTFIELDS] = $data;
243
        }
244
245
        if (!empty($this->customCurlOptions)) {
246
            $options = $this->customCurlOptions + $options;
247
        }
248
249
        $response = self::jsonValidate($this->executeCurl($options), $this->returnArray);
250
251
        if (\is_array($response)) {
252
            if (!isset($response['ok']) || !$response['ok']) {
253
                throw new Exception($response['description'], $response['error_code']);
254
            }
255
256
            return $response['result'];
257
        }
258
259
        if (!$response->ok) {
260
            throw new Exception($response->description, $response->error_code);
261
        }
262
263
        return $response->result;
264
    }
265
266
    /**
267
     * curl_exec wrapper for response validation
268
     *
269
     * @param array $options
270
     *
271
     * @return string
272
     *
273
     * @throws HttpException
274
     */
275
    protected function executeCurl(array $options)
276
    {
277
        curl_setopt_array($this->curl, $options);
278
279
        /** @var string|false $result */
280
        $result = curl_exec($this->curl);
281
        self::curlValidate($this->curl, $result);
282
        if ($result === false) {
0 ignored issues
show
introduced by
The condition $result === false is always false.
Loading history...
283
            throw new HttpException(curl_error($this->curl), curl_errno($this->curl));
284
        }
285
286
        return $result;
287
    }
288
289
    /**
290
     * Response validation
291
     *
292
     * @param resource $curl
293
     * @param string|false|null $response
294
     *
295
     * @throws HttpException
296
     *
297
     * @return void
298
     */
299
    public static function curlValidate($curl, $response = null)
300
    {
301
        if ($response) {
302
            $json = json_decode($response, true) ?: [];
303
        } else {
304
            $json = [];
305
        }
306
        if (($httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE))
307
            && !in_array($httpCode, [self::DEFAULT_STATUS_CODE, self::NOT_MODIFIED_STATUS_CODE])
308
        ) {
309
            $errorDescription = array_key_exists('description', $json) ? $json['description'] : self::$codes[$httpCode];
310
            $errorParameters = array_key_exists('parameters', $json) ? $json['parameters'] : [];
311
            throw new HttpException($errorDescription, $httpCode, null, $errorParameters);
312
        }
313
    }
314
315
    /**
316
     * JSON validation
317
     *
318
     * @param string $jsonString
319
     * @param bool $asArray
320
     *
321
     * @return object|array
322
     * @throws InvalidJsonException
323
     */
324
    public static function jsonValidate($jsonString, $asArray)
325
    {
326
        $json = json_decode($jsonString, $asArray);
327
328
        if (json_last_error() != JSON_ERROR_NONE) {
329
            throw new InvalidJsonException(json_last_error_msg(), json_last_error());
330
        }
331
332
        return $json;
333
    }
334
335
    /**
336
     * Use this method to send text messages. On success, the sent \TelegramBot\Api\Types\Message is returned.
337
     *
338
     * @param int|float|string $chatId
339
     * @param string $text
340
     * @param string|null $parseMode
341
     * @param bool $disablePreview
342
     * @param int|null $replyToMessageId
343
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
344
     * @param bool $disableNotification
345
     * @param int|null $messageThreadId
346
     * @param bool|null $protectContent
347
     * @param bool|null $allowSendingWithoutReply
348
     *
349
     * @return Message
350
     * @throws InvalidArgumentException
351
     * @throws Exception
352
     */
353
    public function sendMessage(
354
        $chatId,
355
        $text,
356
        $parseMode = null,
357
        $disablePreview = false,
358
        $replyToMessageId = null,
359
        $replyMarkup = null,
360
        $disableNotification = false,
361
        $messageThreadId = null,
362
        $protectContent = null,
363
        $allowSendingWithoutReply = null
364
    ) {
365
        return Message::fromResponse($this->call('sendMessage', [
366
            'chat_id' => $chatId,
367
            'text' => $text,
368
            'message_thread_id' => $messageThreadId,
369
            'parse_mode' => $parseMode,
370
            'disable_web_page_preview' => $disablePreview,
371
            'reply_to_message_id' => (int) $replyToMessageId,
372
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
373
            'disable_notification' => (bool) $disableNotification,
374
            'protect_content' => (bool) $protectContent,
375
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
376
        ]));
377
    }
378
379
    /**
380
     * @param int|string $chatId
381
     * @param int|string $fromChatId
382
     * @param int $messageId
383
     * @param string|null $caption
384
     * @param string|null $parseMode
385
     * @param ArrayOfMessageEntity|null $captionEntities
386
     * @param bool $disableNotification
387
     * @param int|null $replyToMessageId
388
     * @param bool $allowSendingWithoutReply
389
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
390
     * @param int|null $messageThreadId
391
     * @param bool|null $protectContent
392
     *
393
     * @return MessageId
394
     * @throws Exception
395
     * @throws HttpException
396
     * @throws InvalidJsonException
397
     */
398
    public function copyMessage(
399
        $chatId,
400
        $fromChatId,
401
        $messageId,
402
        $caption = null,
403
        $parseMode = null,
404
        $captionEntities = null,
405
        $disableNotification = false,
406
        $replyToMessageId = null,
407
        $allowSendingWithoutReply = false,
408
        $replyMarkup = null,
409
        $messageThreadId = null,
410
        $protectContent = null
411
    ) {
412
        return MessageId::fromResponse($this->call('copyMessage', [
413
            'chat_id' => $chatId,
414
            'from_chat_id' => $fromChatId,
415
            'message_id' => (int) $messageId,
416
            'caption' => $caption,
417
            'parse_mode' => $parseMode,
418
            'caption_entities' => $captionEntities,
419
            'disable_notification' => (bool) $disableNotification,
420
            'message_thread_id' => $messageThreadId,
421
            'reply_to_message_id' => (int) $replyToMessageId,
422
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
423
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
424
            'protect_content' => (bool) $protectContent,
425
        ]));
426
    }
427
428
    /**
429
     * Use this method to send phone contacts
430
     *
431
     * @param int|string $chatId chat_id or @channel_name
432
     * @param string $phoneNumber
433
     * @param string $firstName
434
     * @param string $lastName
435
     * @param int|null $replyToMessageId
436
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
437
     * @param bool $disableNotification
438
     * @param int|null $messageThreadId
439
     * @param bool|null $protectContent
440
     * @param bool|null $allowSendingWithoutReply
441
     *
442
     * @return Message
443
     * @throws Exception
444
     */
445
    public function sendContact(
446
        $chatId,
447
        $phoneNumber,
448
        $firstName,
449
        $lastName = null,
450
        $replyToMessageId = null,
451
        $replyMarkup = null,
452
        $disableNotification = false,
453
        $messageThreadId = null,
454
        $protectContent = null,
455
        $allowSendingWithoutReply = null
456
    ) {
457
        return Message::fromResponse($this->call('sendContact', [
458
            'chat_id' => $chatId,
459
            'phone_number' => $phoneNumber,
460
            'first_name' => $firstName,
461
            'last_name' => $lastName,
462
            'message_thread_id' => $messageThreadId,
463
            'reply_to_message_id' => $replyToMessageId,
464
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
465
            'disable_notification' => (bool) $disableNotification,
466
            'protect_content' => (bool) $protectContent,
467
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
468
        ]));
469
    }
470
471
    /**
472
     * Use this method when you need to tell the user that something is happening on the bot's side.
473
     * The status is set for 5 seconds or less (when a message arrives from your bot,
474
     * Telegram clients clear its typing status).
475
     *
476
     * We only recommend using this method when a response from the bot will take a noticeable amount of time to arrive.
477
     *
478
     * Type of action to broadcast. Choose one, depending on what the user is about to receive:
479
     * `typing` for text messages, `upload_photo` for photos, `record_video` or `upload_video` for videos,
480
     * `record_audio` or upload_audio for audio files, `upload_document` for general files,
481
     * `find_location` for location data.
482
     *
483
     * @param int $chatId
484
     * @param string $action
485
     *
486
     * @return bool
487
     * @throws Exception
488
     */
489
    public function sendChatAction($chatId, $action)
490
    {
491
        return $this->call('sendChatAction', [
492
            'chat_id' => $chatId,
493
            'action' => $action,
494
        ]);
495
    }
496
497
    /**
498
     * Use this method to get a list of profile pictures for a user.
499
     *
500
     * @param int $userId
501
     * @param int $offset
502
     * @param int $limit
503
     *
504
     * @return UserProfilePhotos
505
     * @throws Exception
506
     */
507
    public function getUserProfilePhotos($userId, $offset = 0, $limit = 100)
508
    {
509
        return UserProfilePhotos::fromResponse($this->call('getUserProfilePhotos', [
510
            'user_id' => (int) $userId,
511
            'offset' => (int) $offset,
512
            'limit' => (int) $limit,
513
        ]));
514
    }
515
516
    /**
517
     * Use this method to specify a url and receive incoming updates via an outgoing webhook.
518
     * Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url,
519
     * containing a JSON-serialized Update.
520
     * In case of an unsuccessful request, we will give up after a reasonable amount of attempts.
521
     *
522
     * @param string $url HTTPS url to send updates to. Use an empty string to remove webhook integration
523
     * @param \CURLFile|string $certificate Upload your public key certificate
524
     *                                      so that the root certificate in use can be checked
525
     * @param string|null $ipAddress The fixed IP address which will be used to send webhook requests
526
     *                               instead of the IP address resolved through DNS
527
     * @param int|null $maxConnections The maximum allowed number of simultaneous HTTPS connections to the webhook
528
     *                                 for update delivery, 1-100. Defaults to 40. Use lower values to limit
529
     *                                 the load on your bot's server, and higher values to increase your bot's throughput.
530
     * @param array|string|null $allowedUpdates A JSON-serialized list of the update types you want your bot to receive.
531
     *                                          For example, specify [“message”, “edited_channel_post”, “callback_query”]
532
     *                                          to only receive updates of these types. See Update for a complete list of available update types.
533
     *                                          Specify an empty list to receive all update types except chat_member (default).
534
     *                                          If not specified, the previous setting will be used.
535
     *                                          Please note that this parameter doesn't affect updates created before the call to the setWebhook,
536
     *                                          so unwanted updates may be received for a short period of time.
537
     * @param bool|null $dropPendingUpdates Pass True to drop all pending updates
538
     * @param string|null $secretToken A secret token to be sent in a header “X-Telegram-Bot-Api-Secret-Token” in every webhook request,
539
     *                                 1-256 characters. Only characters A-Z, a-z, 0-9, _ and - are allowed.
540
     *                                 The header is useful to ensure that the request comes from a webhook set by you.
541
     *
542
     * @return string
543
     *
544
     * @throws Exception
545
     */
546
    public function setWebhook(
547
        $url = '',
548
        $certificate = null,
549
        $ipAddress = null,
550
        $maxConnections = 40,
551
        $allowedUpdates = null,
552
        $dropPendingUpdates = false,
553
        $secretToken = null
554
    ) {
555
        return $this->call('setWebhook', [
556
            'url' => $url,
557
            'certificate' => $certificate,
558
            'ip_address' => $ipAddress,
559
            'max_connections' => $maxConnections,
560
            'allowed_updates' => \is_array($allowedUpdates) ? json_encode($allowedUpdates) : $allowedUpdates,
561
            'drop_pending_updates' => $dropPendingUpdates,
562
            'secret_token' => $secretToken
563
        ]);
564
    }
565
566
    /**
567
     * Use this method to clear webhook and use getUpdates again!
568
     *
569
     * @param bool $dropPendingUpdates Pass True to drop all pending updates
570
     *
571
     * @return mixed
572
     *
573
     * @throws Exception
574
     */
575
    public function deleteWebhook($dropPendingUpdates = false)
576
    {
577
        return $this->call('deleteWebhook', ['drop_pending_updates' => $dropPendingUpdates]);
578
    }
579
580
    /**
581
     * Use this method to get current webhook status. Requires no parameters.
582
     * On success, returns a WebhookInfo object. If the bot is using getUpdates,
583
     * will return an object with the url field empty.
584
     *
585
     * @return WebhookInfo
586
     * @throws Exception
587
     * @throws InvalidArgumentException
588
     */
589
    public function getWebhookInfo()
590
    {
591
        return WebhookInfo::fromResponse($this->call('getWebhookInfo'));
592
    }
593
594
    /**
595 2
     * A simple method for testing your bot's auth token.Requires no parameters.
596
     * Returns basic information about the bot in form of a User object.
597 2
     *
598 2
     * @return User
599 2
     * @throws Exception
600 2
     * @throws InvalidArgumentException
601 2
     */
602
    public function getMe()
603 2
    {
604
        return User::fromResponse($this->call('getMe'));
605
    }
606
607
    /**
608
     * Use this method to receive incoming updates using long polling.
609 2
     * An Array of Update objects is returned.
610
     *
611
     * Notes
612
     * 1. This method will not work if an outgoing webhook is set up.
613
     * 2. In order to avoid getting duplicate updates, recalculate offset after each server response.
614
     *
615
     * @param int $offset
616
     * @param int $limit
617
     * @param int $timeout
618
     *
619
     * @return Update[]
620
     * @throws Exception
621
     * @throws InvalidArgumentException
622
     */
623
    public function getUpdates($offset = 0, $limit = 100, $timeout = 0)
624
    {
625
        $updates = ArrayOfUpdates::fromResponse($this->call('getUpdates', [
626
            'offset' => $offset,
627
            'limit' => $limit,
628
            'timeout' => $timeout,
629
        ]));
630
631
        if ($this->tracker instanceof Botan) {
632
            foreach ($updates as $update) {
633
                $this->trackUpdate($update);
634
            }
635
        }
636
637
        return $updates;
638
    }
639
640
    /**
641
     * Use this method to send point on the map. On success, the sent Message is returned.
642
     *
643
     * @param int|string $chatId
644
     * @param float $latitude
645
     * @param float $longitude
646
     * @param int|null $replyToMessageId
647
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
648
     * @param bool $disableNotification
649
     * @param null|int $livePeriod
650
     * @param int|null $messageThreadId
651
     * @param bool|null $protectContent
652
     * @param bool|null $allowSendingWithoutReply
653
     *
654
     * @return Message
655
     *
656
     * @throws Exception
657
     */
658
    public function sendLocation(
659
        $chatId,
660
        $latitude,
661
        $longitude,
662
        $replyToMessageId = null,
663
        $replyMarkup = null,
664
        $disableNotification = false,
665
        $livePeriod = null,
666
        $messageThreadId = null,
667
        $protectContent = null,
668
        $allowSendingWithoutReply = null
669
    ) {
670
        return Message::fromResponse($this->call('sendLocation', [
671
            'chat_id' => $chatId,
672
            'latitude' => $latitude,
673
            'longitude' => $longitude,
674
            'live_period' => $livePeriod,
675
            'message_thread_id' => $messageThreadId,
676
            'reply_to_message_id' => $replyToMessageId,
677
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
678
            'disable_notification' => (bool) $disableNotification,
679
            'protect_content' => (bool) $protectContent,
680
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
681
        ]));
682
    }
683
684
    /**
685
     * Use this method to edit live location messages sent by the bot or via the bot (for inline bots).
686
     * On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned.
687
     *
688
     * @param int|string $chatId
689
     * @param int $messageId
690
     * @param string $inlineMessageId
691
     * @param float $latitude
692
     * @param float $longitude
693
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
694
     *
695
     * @return Message|true
696
     *
697
     * @throws Exception
698
     */
699
    public function editMessageLiveLocation(
700
        $chatId,
701
        $messageId,
702
        $inlineMessageId,
703
        $latitude,
704
        $longitude,
705
        $replyMarkup = null
706
    ) {
707
        $response = $this->call('editMessageLiveLocation', [
708
            'chat_id' => $chatId,
709
            'message_id' => $messageId,
710
            'inline_message_id' => $inlineMessageId,
711
            'latitude' => $latitude,
712
            'longitude' => $longitude,
713
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
714
        ]);
715
        if ($response === true) {
716
            return true;
717
        }
718
719
        return Message::fromResponse($response);
720
    }
721
722
    /**
723
     * Use this method to stop updating a live location message sent by the bot or via the bot (for inline bots) before
724
     * live_period expires.
725
     * On success, if the message is not an inline message, the edited Message is returned, otherwise True is returned.
726
     *
727
     * @param int|string $chatId
728
     * @param int $messageId
729
     * @param string $inlineMessageId
730
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
731
     *
732
     * @return Message|true
733
     *
734
     * @throws Exception
735
     */
736
    public function stopMessageLiveLocation(
737
        $chatId,
738
        $messageId,
739
        $inlineMessageId,
740
        $replyMarkup = null
741
    ) {
742
        $response = $this->call('stopMessageLiveLocation', [
743
            'chat_id' => $chatId,
744
            'message_id' => $messageId,
745
            'inline_message_id' => $inlineMessageId,
746
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
747
        ]);
748
        if ($response === true) {
749
            return true;
750
        }
751
752
        return Message::fromResponse($response);
753
    }
754
755
    /**
756
     * Use this method to send information about a venue. On success, the sent Message is returned.
757
     *
758
     * @param int|string $chatId chat_id or @channel_name
759
     * @param float $latitude
760
     * @param float $longitude
761
     * @param string $title
762
     * @param string $address
763
     * @param string|null $foursquareId
764
     * @param int|null $replyToMessageId
765
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
766
     * @param bool $disableNotification
767
     * @param int|null $messageThreadId
768
     * @param bool|null $protectContent
769
     * @param bool|null $allowSendingWithoutReply
770
     *
771
     * @return Message
772
     * @throws Exception
773
     */
774
    public function sendVenue(
775
        $chatId,
776
        $latitude,
777
        $longitude,
778
        $title,
779
        $address,
780
        $foursquareId = null,
781
        $replyToMessageId = null,
782
        $replyMarkup = null,
783
        $disableNotification = false,
784
        $messageThreadId = null,
785
        $protectContent = null,
786
        $allowSendingWithoutReply = null
787
    ) {
788
        return Message::fromResponse($this->call('sendVenue', [
789
            'chat_id' => $chatId,
790
            'latitude' => $latitude,
791
            'longitude' => $longitude,
792
            'title' => $title,
793
            'address' => $address,
794
            'foursquare_id' => $foursquareId,
795
            'message_thread_id' => $messageThreadId,
796
            'reply_to_message_id' => $replyToMessageId,
797
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
798
            'disable_notification' => (bool) $disableNotification,
799
            'protect_content' => (bool) $protectContent,
800
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
801
        ]));
802
    }
803
804
    /**
805
     * Use this method to send .webp stickers. On success, the sent Message is returned.
806
     *
807
     * @param int|string $chatId chat_id or @channel_name
808
     * @param \CURLFile|string $sticker
809
     * @param int|null $replyToMessageId
810
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
811
     * @param bool $disableNotification Sends the message silently. Users will receive a notification with no sound.
812
     * @param bool $protectContent Protects the contents of the sent message from forwarding and saving
813
     * @param bool $allowSendingWithoutReply Pass True if the message should be sent even if the specified replied-to message is not found
814
     * @param string|null $messageThreadId
815
     *
816
     * @return Message
817
     * @throws InvalidArgumentException
818
     * @throws Exception
819
     */
820
    public function sendSticker(
821
        $chatId,
822
        $sticker,
823
        $replyToMessageId = null,
824
        $replyMarkup = null,
825
        $disableNotification = false,
826
        $protectContent = false,
827
        $allowSendingWithoutReply = false,
828
        $messageThreadId = null
829
    ) {
830
        return Message::fromResponse($this->call('sendSticker', [
831
            'chat_id' => $chatId,
832
            'sticker' => $sticker,
833
            'message_thread_id' => $messageThreadId,
834
            'reply_to_message_id' => $replyToMessageId,
835
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
836
            'disable_notification' => (bool) $disableNotification,
837
            'protect_content' => (bool) $protectContent,
838
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
839
        ]));
840
    }
841
842
    /**
843
     * @param string $name Name of the sticker set
844
     * @return StickerSet
845
     * @throws InvalidArgumentException
846
     * @throws Exception
847
     */
848
    public function getStickerSet($name)
849
    {
850
        return StickerSet::fromResponse($this->call('getStickerSet', [
851
            'name' => $name,
852
        ]));
853
    }
854
855
    /**
856
     * @param array[] $customEmojiIds List of custom emoji identifiers.
857
     *                                At most 200 custom emoji identifiers can be specified.
858
     * @return StickerSet
859
     * @throws InvalidArgumentException
860
     * @throws Exception
861
     *
862
     * @author bernard-ng <[email protected]>
863
     */
864
    public function getCustomEmojiStickers($customEmojiIds = [])
865
    {
866
        return StickerSet::fromResponse($this->call('getCustomEmojiStickers', [
867
            'custom_emoji_ids' => $customEmojiIds,
868
        ]));
869
    }
870
871
    /**
872
     * Use this method to create a new sticker set owned by a user.
873
     * The bot will be able to edit the sticker set thus created.
874
     * You must use exactly one of the fields png_sticker, tgs_sticker, or webm_sticker.
875
     * Returns True on success.
876
     *
877
     * @param int $userId User identifier of created sticker set owner
878
     * @param string $pngSticker PNG image with the sticker, must be up to 512 kilobytes in size,
879
     *                           dimensions must not exceed 512px, and either width or height must be exactly 512px.
880
     *
881
     * @return File
882
     *
883
     * @throws InvalidArgumentException
884
     * @throws Exception
885
     */
886
    public function uploadStickerFile($userId, $pngSticker)
887
    {
888
        return File::fromResponse($this->call('uploadStickerFile', [
889
            'user_id' => $userId,
890
            'png_sticker' => $pngSticker,
891
        ]));
892
    }
893
894
    /**
895
     * Use this method to create a new sticker set owned by a user.
896
     * The bot will be able to edit the sticker set thus created.
897
     * You must use exactly one of the fields png_sticker, tgs_sticker, or webm_sticker. Returns True on success.
898
     *
899
     * @param int $userId User identifier of created sticker set owner
900
     * @param string $name Short name of sticker set, to be used in t.me/addstickers/ URLs (e.g., animals).
901
     *                     Can contain only english letters, digits and underscores. Must begin with a letter,
902
     *                     can't contain consecutive underscores and must end in “_by_<bot username>”.
903
     *                     <bot_username> is case insensitive. 1-64 characters.
904
     * @param string $title Sticker set title, 1-64 characters
905
     * @param string $pngSticker PNG image with the sticker, must be up to 512 kilobytes in size,
906
     *                           dimensions must not exceed 512px, and either width or height must be exactly 512px.
907
     *                           Pass a file_id as a String to send a file that already exists on the Telegram servers,
908
     *                           pass an HTTP URL as a String for Telegram to get a file from the Internet,
909
     *                           or upload a new one using multipart/form-data.
910
     * @param string $tgsSticker TGS animation with the sticker, uploaded using multipart/form-data.
911
     *                           See https://core.telegram.org/animated_stickers#technical-requirements for technical requirements
912
     * @param string $webmSticker WebP animation with the sticker, uploaded using multipart/form-data.
913
     *                            See https://core.telegram.org/animated_stickers#technical-requirements for technical requirements
914
     * @param string $stickerType Sticker type, one of “png”, “tgs”, or “webp”
915
     * @param string $emojis One or more emoji corresponding to the sticker
916
     * @param MaskPosition|null $maskPosition A JSON-serialized object for position where the mask should be placed on faces
917
     * @param array<string, \CURLFile|\CURLStringFile> $attachments Attachments to use in attach://<attachment>
918
     *
919
     * @throws InvalidArgumentException
920
     * @throws Exception
921
     *
922
     * @return bool
923
     *
924
     * @author bernard-ng <[email protected]>
925
     */
926
    public function createNewStickerSet(
927
        $userId,
928
        $name,
929
        $title,
930
        $emojis,
931
        $pngSticker,
932
        $tgsSticker = null,
933
        $webmSticker = null,
934
        $stickerType = null,
935
        $maskPosition = null,
936
        $attachments = []
937
    ) {
938
        return $this->call('createNewStickerSet', [
939
            'user_id' => $userId,
940
            'name' => $name,
941
            'title' => $title,
942
            'png_sticker' => $pngSticker,
943
            'tgs_sticker' => $tgsSticker,
944
            'webm_sticker' => $webmSticker,
945
            'sticker_type' => $stickerType,
946
            'emojis' => $emojis,
947
            'mask_position' => is_null($maskPosition) ? $maskPosition : $maskPosition->toJson(),
948
        ] + $attachments);
949
    }
950
951
    /**
952
     * Use this method to add a new sticker to a set created by the bot.
953
     * You must use exactly one of the fields png_sticker, tgs_sticker, or webm_sticker.
954
     * Animated stickers can be added to animated sticker sets and only to them.
955
     * Animated sticker sets can have up to 50 stickers.
956
     * Static sticker sets can have up to 120 stickers. Returns True on success.
957
     *
958
     * @param string $userId
959
     * @param string $name
960
     * @param string $emojis
961
     * @param string $pngSticker
962
     * @param string|null $tgsSticker
963
     * @param string|null $webmSticker
964
     * @param MaskPosition|null $maskPosition
965
     * @param array<string, \CURLFile|\CURLStringFile> $attachments Attachments to use in attach://<attachment>
966
     *
967
     * @return bool
968
     * @throws Exception
969
     * @throws HttpException
970
     * @throws InvalidJsonException
971
     */
972
    public function addStickerToSet(
973
        $userId,
974
        $name,
975
        $emojis,
976
        $pngSticker,
977
        $tgsSticker = null,
978
        $webmSticker = null,
979
        $maskPosition = null,
980
        $attachments = []
981
    ) {
982
        return $this->call('addStickerToSet', [
983
            'user_id' => $userId,
984
            'name' => $name,
985
            'png_sticker' => $pngSticker,
986
            'tgs_sticker' => $tgsSticker,
987
            'webm_sticker' => $webmSticker,
988
            'emojis' => $emojis,
989
            'mask_position' => is_null($maskPosition) ? $maskPosition : $maskPosition->toJson(),
990
        ] + $attachments);
991
    }
992
993
    /**
994
     * Use this method to move a sticker in a set created by the bot to a specific position.
995
     * Returns True on success.
996
     *
997
     * @param string $sticker File identifier of the sticker
998
     * @param int $position New sticker position in the set, zero-based
999
     *
1000
     * @return bool
1001
     *
1002
     * @throws InvalidArgumentException
1003
     * @throws Exception
1004
     */
1005
    public function setStickerPositionInSet($sticker, $position)
1006
    {
1007
        return $this->call('setStickerPositionInSet', [
1008
            'sticker' => $sticker,
1009
            'position' => $position,
1010
        ]);
1011
    }
1012
1013
    /**
1014
     * Use this method to delete a sticker from a set created by the bot.
1015
     * Returns True on success.
1016
     *
1017
     * @param string $name Sticker set name
1018
     * @param string $userId User identifier of sticker set owner
1019
     * @param File|null $thumbnail A PNG image with the thumbnail,
1020
     *                             must be up to 128 kilobytes in size and have width and height exactly 100px,
1021
     *                             or a TGS animation with the thumbnail up to 32 kilobytes in size
1022
     *
1023
     * @return bool
1024
     *
1025
     * @throws InvalidArgumentException
1026
     * @throws Exception
1027
     */
1028
    public function setStickerSetThumbnail($name, $userId, $thumbnail = null)
1029
    {
1030
        return $this->call('setStickerSetThumb', [
1031
            'name' => $name,
1032
            'user_id' => $userId,
1033
            'thumbnail' => $thumbnail,
1034
        ]);
1035
    }
1036
1037
    /**
1038
     * @deprecated Use setStickerSetThumbnail
1039
     *
1040
     * Use this method to delete a sticker from a set created by the bot.
1041
     * Returns True on success.
1042
     *
1043
     * @param string $name Sticker set name
1044
     * @param string $userId User identifier of sticker set owner
1045
     * @param File|null $thumb A PNG image with the thumbnail,
1046
     *                         must be up to 128 kilobytes in size and have width and height exactly 100px,
1047
     *                         or a TGS animation with the thumbnail up to 32 kilobytes in size
1048
     *
1049
     * @return bool
1050
     *
1051
     * @throws InvalidArgumentException
1052
     * @throws Exception
1053
     */
1054
    public function setStickerSetThumb($name, $userId, $thumb = null)
1055
    {
1056
        return $this->setStickerSetThumbnail($name, $userId, $thumb);
1057
    }
1058
1059
    /**
1060
     * Use this method to send video files,
1061
     * Telegram clients support mp4 videos (other formats may be sent as Document).
1062
     * On success, the sent Message is returned.
1063
     *
1064
     * @param int|string $chatId chat_id or @channel_name
1065
     * @param \CURLFile|string $video
1066
     * @param int|null $duration
1067
     * @param string|null $caption
1068
     * @param int|null $replyToMessageId
1069
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
1070
     * @param bool $disableNotification
1071
     * @param bool $supportsStreaming Pass True, if the uploaded video is suitable for streaming
1072
     * @param string|null $parseMode
1073
     * @param int|null $messageThreadId
1074
     * @param bool|null $protectContent
1075
     * @param bool|null $allowSendingWithoutReply
1076
     * @param \CURLFile|\CURLStringFile|string|null $thumbnail
0 ignored issues
show
Bug introduced by
The type CURLStringFile was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1077
     *
1078
     * @return Message
1079
     * @throws InvalidArgumentException
1080
     * @throws Exception
1081
     */
1082
    public function sendVideo(
1083
        $chatId,
1084
        $video,
1085
        $duration = null,
1086
        $caption = null,
1087
        $replyToMessageId = null,
1088
        $replyMarkup = null,
1089
        $disableNotification = false,
1090
        $supportsStreaming = false,
1091
        $parseMode = null,
1092
        $messageThreadId = null,
1093
        $protectContent = null,
1094
        $allowSendingWithoutReply = null,
1095
        $thumbnail = null
1096
    ) {
1097
        return Message::fromResponse($this->call('sendVideo', [
1098
            'chat_id' => $chatId,
1099
            'video' => $video,
1100
            'duration' => $duration,
1101
            'caption' => $caption,
1102
            'message_thread_id' => $messageThreadId,
1103
            'reply_to_message_id' => $replyToMessageId,
1104
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1105
            'disable_notification' => (bool) $disableNotification,
1106
            'supports_streaming' => (bool) $supportsStreaming,
1107
            'parse_mode' => $parseMode,
1108
            'protect_content' => (bool) $protectContent,
1109
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1110
            'thumbnail' => $thumbnail,
1111
        ]));
1112
    }
1113
1114
    /**
1115
     * Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound),
1116
     * On success, the sent Message is returned.
1117
     * Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future.
1118
     *
1119
     * @param int|string $chatId chat_id or @channel_name
1120
     * @param \CURLFile|string $animation
1121
     * @param int|null $duration
1122
     * @param string|null $caption
1123
     * @param int|null $replyToMessageId
1124
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
1125
     * @param bool $disableNotification
1126
     * @param string|null $parseMode,
1127
     * @param int|null $messageThreadId
1128
     * @param bool|null $protectContent
1129
     * @param bool|null $allowSendingWithoutReply
1130
     * @param \CURLFile|\CURLStringFile|string|null $thumbnail
1131
     *
1132
     * @return Message
1133
     * @throws InvalidArgumentException
1134
     * @throws Exception
1135
     */
1136
    public function sendAnimation(
1137
        $chatId,
1138
        $animation,
1139
        $duration = null,
1140
        $caption = null,
1141
        $replyToMessageId = null,
1142
        $replyMarkup = null,
1143
        $disableNotification = false,
1144
        $parseMode = null,
1145
        $messageThreadId = null,
1146
        $protectContent = null,
1147
        $allowSendingWithoutReply = null,
1148
        $thumbnail = null
1149
    ) {
1150
        return Message::fromResponse($this->call('sendAnimation', [
1151
            'chat_id' => $chatId,
1152
            'animation' => $animation,
1153
            'duration' => $duration,
1154
            'caption' => $caption,
1155
            'message_thread_id' => $messageThreadId,
1156
            'reply_to_message_id' => $replyToMessageId,
1157
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1158
            'disable_notification' => (bool) $disableNotification,
1159
            'parse_mode' => $parseMode,
1160
            'protect_content' => (bool) $protectContent,
1161
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1162
            'thumbnail' => $thumbnail,
1163
        ]));
1164
    }
1165
1166
    /**
1167
     * Use this method to send audio files,
1168
     * if you want Telegram clients to display the file as a playable voice message.
1169
     * For this to work, your audio must be in an .ogg file encoded with OPUS
1170
     * (other formats may be sent as Audio or Document).
1171
     * On success, the sent Message is returned.
1172
     * Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future.
1173
     *
1174
     * @param int|string $chatId chat_id or @channel_name
1175
     * @param \CURLFile|string $voice
1176
     * @param string $caption Voice message caption, 0-1024 characters after entities parsing
1177
     * @param int|null $duration
1178
     * @param int|null $replyToMessageId
1179
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
1180
     * @param bool $disableNotification
1181
     * @param bool $allowSendingWithoutReply Pass True, if the message should be sent even if the specified
1182
     *                                       replied-to message is not found
1183
     * @param string|null $parseMode
1184
     * @param int|null $messageThreadId
1185
     * @param bool|null $protectContent
1186
     *
1187
     * @return Message
1188
     * @throws InvalidArgumentException
1189
     * @throws Exception
1190
     */
1191
    public function sendVoice(
1192
        $chatId,
1193
        $voice,
1194
        $caption = null,
1195
        $duration = null,
1196
        $replyToMessageId = null,
1197
        $replyMarkup = null,
1198
        $disableNotification = false,
1199
        $allowSendingWithoutReply = false,
1200
        $parseMode = null,
1201
        $messageThreadId = null,
1202
        $protectContent = null
1203
    ) {
1204
        return Message::fromResponse($this->call('sendVoice', [
1205
            'chat_id' => $chatId,
1206
            'voice' => $voice,
1207
            'caption' => $caption,
1208
            'duration' => $duration,
1209
            'message_thread_id' => $messageThreadId,
1210
            'reply_to_message_id' => $replyToMessageId,
1211
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1212
            'disable_notification' => (bool) $disableNotification,
1213
            'allow_sending_without_reply' => $allowSendingWithoutReply,
1214
            'parse_mode' => $parseMode,
1215
            'protect_content' => (bool) $protectContent,
1216
        ]));
1217
    }
1218
1219
    /**
1220
     * Use this method to forward messages of any kind. Service messages can't be forwarded.
1221
     * On success, the sent Message is returned.
1222
     *
1223
     * @param int|string $chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername)
1224
     * @param int $fromChatId Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername)
1225
     * @param string $messageId Message identifier in the chat specified in from_chat_id
1226
     * @param bool $protectContent Protects the contents of the forwarded message from forwarding and saving
1227
     * @param bool $disableNotification Sends the message silently. Users will receive a notification with no sound.
1228
     * @param int|null $messageThreadId Unique identifier for the target message thread (topic) of the forum; for forum supergroups only
1229
     *
1230
     * @return Message
1231
     * @throws Exception
1232
     * @throws HttpException
1233
     * @throws InvalidJsonException
1234
     */
1235
    public function forwardMessage(
1236
        $chatId,
1237
        $fromChatId,
1238
        $messageId,
1239
        $protectContent = false,
1240
        $disableNotification = false,
1241
        $messageThreadId = null
1242
    ) {
1243
        return Message::fromResponse($this->call('forwardMessage', [
1244
            'chat_id' => $chatId,
1245
            'from_chat_id' => $fromChatId,
1246
            'message_id' => $messageId,
1247
            'message_thread_id' => $messageThreadId,
1248
            'protect_content' => $protectContent,
1249
            'disable_notification' => (bool) $disableNotification,
1250
        ]));
1251
    }
1252
1253
    /**
1254
     * Use this method to send audio files,
1255
     * if you want Telegram clients to display them in the music player.
1256
     * Your audio must be in the .mp3 format.
1257
     * On success, the sent Message is returned.
1258
     * Bots can currently send audio files of up to 50 MB in size, this limit may be changed in the future.
1259
     *
1260
     * For backward compatibility, when the fields title and performer are both empty
1261
     * and the mime-type of the file to be sent is not audio/mpeg, the file will be sent as a playable voice message.
1262
     * For this to work, the audio must be in an .ogg file encoded with OPUS.
1263
     * This behavior will be phased out in the future. For sending voice messages, use the sendVoice method instead.
1264
     *
1265
     * @param int|string $chatId chat_id or @channel_name
1266
     * @param \CURLFile|string $audio
1267
     * @param int|null $duration
1268
     * @param string|null $performer
1269
     * @param string|null $title
1270
     * @param int|null $replyToMessageId
1271
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
1272
     * @param bool $disableNotification
1273
     * @param string|null $parseMode
1274
     * @param bool|null $protectContent
1275
     * @param bool|null $allowSendingWithoutReply
1276
     * @param \CURLFile|\CURLStringFile|string|null $thumbnail
1277
     *
1278
     * @return Message
1279
     * @throws InvalidArgumentException
1280
     * @throws Exception
1281
     * @deprecated since 20th February. Removed backward compatibility from the method sendAudio.
1282
     * Voice messages now must be sent using the method sendVoice.
1283
     * There is no more need to specify a non-empty title or performer while sending the audio by file_id.
1284
     *
1285
     */
1286
    public function sendAudio(
1287
        $chatId,
1288
        $audio,
1289
        $duration = null,
1290
        $performer = null,
1291
        $title = null,
1292
        $replyToMessageId = null,
1293
        $replyMarkup = null,
1294
        $disableNotification = false,
1295
        $parseMode = null,
1296
        $protectContent = null,
1297
        $allowSendingWithoutReply = null,
1298
        $thumbnail = null
1299
    ) {
1300
        return Message::fromResponse($this->call('sendAudio', [
1301
            'chat_id' => $chatId,
1302
            'audio' => $audio,
1303
            'duration' => $duration,
1304
            'performer' => $performer,
1305
            'title' => $title,
1306
            'reply_to_message_id' => $replyToMessageId,
1307
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1308
            'disable_notification' => (bool) $disableNotification,
1309
            'parse_mode' => $parseMode,
1310
            'protect_content' => (bool) $protectContent,
1311
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1312
            'thumbnail' => $thumbnail,
1313
        ]));
1314
    }
1315
1316
    /**
1317
     * Use this method to send photos. On success, the sent Message is returned.
1318
     *
1319
     * @param int|string $chatId chat_id or @channel_name
1320
     * @param \CURLFile|string $photo
1321
     * @param string|null $caption
1322
     * @param int|null $replyToMessageId
1323
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
1324
     * @param bool $disableNotification
1325
     * @param string|null $parseMode
1326
     * @param int|null $messageThreadId
1327
     * @param bool|null $protectContent
1328
     * @param bool|null $allowSendingWithoutReply
1329
     *
1330
     * @return Message
1331
     * @throws InvalidArgumentException
1332
     * @throws Exception
1333
     */
1334
    public function sendPhoto(
1335
        $chatId,
1336
        $photo,
1337
        $caption = null,
1338
        $replyToMessageId = null,
1339
        $replyMarkup = null,
1340
        $disableNotification = false,
1341
        $parseMode = null,
1342
        $messageThreadId = null,
1343
        $protectContent = null,
1344
        $allowSendingWithoutReply = null
1345
    ) {
1346
        return Message::fromResponse($this->call('sendPhoto', [
1347
            'chat_id' => $chatId,
1348
            'photo' => $photo,
1349
            'caption' => $caption,
1350
            'message_thread_id' => $messageThreadId,
1351
            'reply_to_message_id' => $replyToMessageId,
1352
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1353
            'disable_notification' => (bool) $disableNotification,
1354
            'parse_mode' => $parseMode,
1355
            'protect_content' => (bool) $protectContent,
1356
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1357
        ]));
1358
    }
1359
1360
    /**
1361
     * Use this method to send general files. On success, the sent Message is returned.
1362
     * Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future.
1363
     *
1364
     * @param int|string $chatId chat_id or @channel_name
1365
     * @param \CURLFile|\CURLStringFile|string $document
1366
     * @param string|null $caption
1367
     * @param int|null $replyToMessageId
1368
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
1369
     * @param bool $disableNotification
1370
     * @param string|null $parseMode
1371
     * @param int|null $messageThreadId
1372
     * @param bool|null $protectContent
1373
     * @param bool|null $allowSendingWithoutReply
1374
     * @param \CURLFile|\CURLStringFile|string|null $thumbnail
1375
     *
1376
     * @return Message
1377
     * @throws InvalidArgumentException
1378
     * @throws Exception
1379
     */
1380
    public function sendDocument(
1381
        $chatId,
1382
        $document,
1383
        $caption = null,
1384
        $replyToMessageId = null,
1385
        $replyMarkup = null,
1386
        $disableNotification = false,
1387
        $parseMode = null,
1388
        $messageThreadId = null,
1389
        $protectContent = null,
1390
        $allowSendingWithoutReply = null,
1391
        $thumbnail = null
1392
    ) {
1393
        return Message::fromResponse($this->call('sendDocument', [
1394
            'chat_id' => $chatId,
1395
            'document' => $document,
1396
            'caption' => $caption,
1397
            'message_thread_id' => $messageThreadId,
1398
            'reply_to_message_id' => $replyToMessageId,
1399
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1400
            'disable_notification' => (bool) $disableNotification,
1401
            'parse_mode' => $parseMode,
1402
            'protect_content' => (bool) $protectContent,
1403
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1404
            'thumbnail' => $thumbnail,
1405
        ]));
1406
    }
1407
1408
    /**
1409
     * Use this method to get basic info about a file and prepare it for downloading.
1410
     * For the moment, bots can download files of up to 20MB in size.
1411
     * On success, a File object is returned.
1412
     * The file can then be downloaded via the link https://api.telegram.org/file/bot<token>/<file_path>,
1413
     * where <file_path> is taken from the response.
1414
     * It is guaranteed that the link will be valid for at least 1 hour.
1415
     * When the link expires, a new one can be requested by calling getFile again.
1416
     *
1417
     * @param string $fileId
1418
     *
1419
     * @return File
1420
     * @throws InvalidArgumentException
1421
     * @throws Exception
1422
     */
1423
    public function getFile($fileId)
1424
    {
1425
        return File::fromResponse($this->call('getFile', ['file_id' => $fileId]));
1426
    }
1427
1428
    /**
1429
     * Get file contents via cURL
1430
     *
1431
     * @param string $fileId
1432
     *
1433
     * @return string
1434
     *
1435
     * @throws HttpException
1436
     * @throws Exception
1437
     */
1438
    public function downloadFile($fileId)
1439
    {
1440
        $file = $this->getFile($fileId);
1441
        $options = [
1442
            CURLOPT_HEADER => 0,
1443
            CURLOPT_HTTPGET => 1,
1444
            CURLOPT_RETURNTRANSFER => 1,
1445
            CURLOPT_URL => $this->getFileUrl().'/'.$file->getFilePath(),
1446
        ];
1447
1448
        return $this->executeCurl($options);
1449
    }
1450
1451
    /**
1452
     * Use this method to send answers to an inline query. On success, True is returned.
1453
     * No more than 50 results per query are allowed.
1454
     *
1455
     * @param string $inlineQueryId
1456
     * @param AbstractInlineQueryResult[] $results
1457
     * @param int $cacheTime
1458
     * @param bool $isPersonal
1459
     * @param string $nextOffset
1460
     * @param string $switchPmText
1461
     * @param string $switchPmParameter
1462
     *
1463
     * @return mixed
1464
     * @throws Exception
1465
     */
1466
    public function answerInlineQuery(
1467
        $inlineQueryId,
1468
        $results,
1469
        $cacheTime = 300,
1470
        $isPersonal = false,
1471
        $nextOffset = '',
1472
        $switchPmText = null,
1473
        $switchPmParameter = null
1474
    ) {
1475
        $results = array_map(
1476
            /**
1477
             * @param AbstractInlineQueryResult $item
1478
             * @return array
1479
             */
1480
            function ($item) {
1481
                /** @var array $array */
1482
                $array = $item->toJson(true);
1483
1484
                return $array;
1485
            },
1486
            $results
1487
        );
1488
1489
        return $this->call('answerInlineQuery', [
1490
            'inline_query_id' => $inlineQueryId,
1491
            'results' => json_encode($results),
1492
            'cache_time' => $cacheTime,
1493
            'is_personal' => $isPersonal,
1494
            'next_offset' => $nextOffset,
1495
            'switch_pm_text' => $switchPmText,
1496
            'switch_pm_parameter' => $switchPmParameter,
1497
        ]);
1498
    }
1499
1500
    /**
1501
     * Use this method to kick a user from a group or a supergroup.
1502
     * In the case of supergroups, the user will not be able to return to the group
1503
     * on their own using invite links, etc., unless unbanned first.
1504
     * The bot must be an administrator in the group for this to work. Returns True on success.
1505
     *
1506
     * @param int|string $chatId Unique identifier for the target group
1507
     *                           or username of the target supergroup (in the format @supergroupusername)
1508
     * @param int $userId Unique identifier of the target user
1509
     * @param null|int $untilDate Date when the user will be unbanned, unix time.
1510
     *                            If user is banned for more than 366 days or less than 30 seconds from the current time
1511
     *                            they are considered to be banned forever
1512
     *
1513
     * @return bool
1514
     * @throws Exception
1515
     */
1516
    public function kickChatMember($chatId, $userId, $untilDate = null)
1517
    {
1518
        return $this->call('kickChatMember', [
1519
            'chat_id' => $chatId,
1520
            'user_id' => $userId,
1521
            'until_date' => $untilDate
1522
        ]);
1523
    }
1524
1525
    /**
1526
     * Use this method to unban a previously kicked user in a supergroup.
1527
     * The user will not return to the group automatically, but will be able to join via link, etc.
1528
     * The bot must be an administrator in the group for this to work. Returns True on success.
1529
     *
1530
     * @param int|string $chatId Unique identifier for the target group
1531
     *                           or username of the target supergroup (in the format @supergroupusername)
1532
     * @param int $userId Unique identifier of the target user
1533
     *
1534
     * @return bool
1535
     * @throws Exception
1536
     */
1537
    public function unbanChatMember($chatId, $userId)
1538
    {
1539
        return $this->call('unbanChatMember', [
1540
            'chat_id' => $chatId,
1541
            'user_id' => $userId,
1542
        ]);
1543
    }
1544
1545
    /**
1546
     * Use this method to send answers to callback queries sent from inline keyboards.
1547
     * The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.
1548
     *
1549
     * @param string $callbackQueryId
1550
     * @param string|null $text
1551
     * @param bool $showAlert
1552
     * @param string|null $url
1553
     * @param int $cacheTime
1554
     *
1555
     * @return bool
1556
     * @throws Exception
1557
     */
1558
    public function answerCallbackQuery($callbackQueryId, $text = null, $showAlert = false, $url = null, $cacheTime = 0)
1559
    {
1560
        return $this->call('answerCallbackQuery', [
1561
            'callback_query_id' => $callbackQueryId,
1562
            'text' => $text,
1563
            'show_alert' => (bool) $showAlert,
1564
            'url' => $url,
1565
            'cache_time' => $cacheTime
1566
        ]);
1567
    }
1568
1569
    /**
1570
     * Use this method to change the list of the bot's commands. Returns True on success.
1571
     *
1572
     * @param ArrayOfBotCommand|BotCommand[] $commands
1573
     * @param string|null $scope
1574
     * @param string|null $languageCode
1575
     *
1576
     * @return mixed
1577
     * @throws Exception
1578
     * @throws HttpException
1579
     * @throws InvalidJsonException
1580
     */
1581
    public function setMyCommands($commands, $scope = null, $languageCode = null)
1582
    {
1583
        if (!$commands instanceof ArrayOfBotCommand) {
1584
            @trigger_error(sprintf('Passing array of BotCommand to "%s::%s" is deprecated. Use %s', __CLASS__, __METHOD__, ArrayOfBotCommand::class), \E_USER_DEPRECATED);
1585
            $commands = new ArrayOfBotCommand($commands);
1586
        }
1587
1588
        return $this->call('setMyCommands', [
1589
            'commands' => $commands->toJson(),
1590
            'scope' => $scope,
1591
            'language_code' => $languageCode,
1592
        ]);
1593
    }
1594
1595
    /**
1596
     * Use this method to get the current list of the bot's commands. Requires no parameters.
1597
     * Returns Array of BotCommand on success.
1598
     *
1599
     * @return ArrayOfBotCommand
1600
     *
1601
     * @throws Exception
1602
     * @throws HttpException
1603
     * @throws InvalidJsonException
1604
     */
1605
    public function getMyCommands()
1606
    {
1607
        return ArrayOfBotCommand::fromResponse($this->call('getMyCommands'));
1608
    }
1609
1610
    /**
1611 9
     * Use this method to edit text messages sent by the bot or via the bot
1612
     * On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned.
1613 9
     *
1614 9
     * @param int|string $chatId
1615
     * @param int $messageId
1616
     * @param string $text
1617
     * @param string $inlineMessageId
1618
     * @param string|null $parseMode
1619
     * @param bool $disablePreview
1620
     * @param InlineKeyboardMarkup|null $replyMarkup
1621
     *
1622
     * @return Message|true
1623
     * @throws Exception
1624
     */
1625
    public function editMessageText(
1626
        $chatId,
1627
        $messageId,
1628
        $text,
1629
        $parseMode = null,
1630
        $disablePreview = false,
1631
        $replyMarkup = null,
1632
        $inlineMessageId = null
1633
    ) {
1634
        $response = $this->call('editMessageText', [
1635
            'chat_id' => $chatId,
1636
            'message_id' => $messageId,
1637
            'text' => $text,
1638
            'inline_message_id' => $inlineMessageId,
1639
            'parse_mode' => $parseMode,
1640
            'disable_web_page_preview' => $disablePreview,
1641
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1642
        ]);
1643
        if ($response === true) {
1644
            return true;
1645
        }
1646
1647
        return Message::fromResponse($response);
1648
    }
1649
1650
    /**
1651
     * Use this method to edit text messages sent by the bot or via the bot
1652
     * On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned.
1653
     *
1654
     * @param int|string $chatId
1655
     * @param int $messageId
1656
     * @param string|null $caption
1657
     * @param InlineKeyboardMarkup|null $replyMarkup
1658
     * @param string $inlineMessageId
1659
     * @param string|null $parseMode
1660
     *
1661
     * @return Message|true
1662
     * @throws InvalidArgumentException
1663
     * @throws Exception
1664
     */
1665
    public function editMessageCaption(
1666
        $chatId,
1667
        $messageId,
1668
        $caption = null,
1669
        $replyMarkup = null,
1670
        $inlineMessageId = null,
1671
        $parseMode = null
1672
    ) {
1673
        $response = $this->call('editMessageCaption', [
1674
            'chat_id' => $chatId,
1675
            'message_id' => $messageId,
1676
            'inline_message_id' => $inlineMessageId,
1677
            'caption' => $caption,
1678
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1679
            'parse_mode' => $parseMode
1680
        ]);
1681
        if ($response === true) {
1682
            return true;
1683
        }
1684
1685
        return Message::fromResponse($response);
1686
    }
1687
1688
    /**
1689
     * Use this method to edit animation, audio, document, photo, or video messages.
1690
     * If a message is a part of a message album, then it can be edited only to a photo or a video.
1691
     * Otherwise, message type can be changed arbitrarily.
1692
     * When inline message is edited, new file can't be uploaded.
1693
     * Use previously uploaded file via its file_id or specify a URL.
1694
     * On success, if the edited message was sent by the bot, the edited Message is returned, otherwise True is returned
1695
     *
1696
     * @param string $chatId
1697
     * @param string $messageId
1698
     * @param InputMedia $media
1699
     * @param string|null $inlineMessageId
1700
     * @param InlineKeyboardMarkup|null $replyMarkup
1701
     * @param array<string, \CURLFile|\CURLStringFile> $attachments Attachments to use in attach://<attachment>
1702
     *
1703
     * @return Message|true
1704
     *
1705
     * @throws Exception
1706
     * @throws HttpException
1707
     * @throws InvalidJsonException
1708
     */
1709
    public function editMessageMedia(
1710
        $chatId,
1711
        $messageId,
1712
        InputMedia $media,
1713
        $inlineMessageId = null,
1714
        $replyMarkup = null,
1715
        $attachments = []
1716
    ) {
1717
        $response = $this->call('editMessageMedia', [
1718
            'chat_id' => $chatId,
1719
            'message_id' => $messageId,
1720
            'inline_message_id' => $inlineMessageId,
1721
            'media' => $media->toJson(),
1722
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1723
        ] + $attachments);
1724
        if ($response === true) {
1725
            return true;
1726
        }
1727
1728
        return Message::fromResponse($response);
1729
    }
1730
1731
    /**
1732
     * Use this method to edit only the reply markup of messages sent by the bot or via the bot
1733
     * On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned.
1734
     *
1735
     * @param int|string $chatId
1736
     * @param int $messageId
1737
     * @param InlineKeyboardMarkup|null $replyMarkup
1738
     * @param string $inlineMessageId
1739
     *
1740
     * @return Message|true
1741
     * @throws Exception
1742
     */
1743
    public function editMessageReplyMarkup(
1744
        $chatId,
1745
        $messageId,
1746
        $replyMarkup = null,
1747
        $inlineMessageId = null
1748
    ) {
1749
        $response = $this->call('editMessageReplyMarkup', [
1750
            'chat_id' => $chatId,
1751
            'message_id' => $messageId,
1752
            'inline_message_id' => $inlineMessageId,
1753
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1754
        ]);
1755
        if ($response === true) {
1756
            return true;
1757
        }
1758
1759
        return Message::fromResponse($response);
1760
    }
1761
1762
    /**
1763
     * Use this method to delete a message, including service messages, with the following limitations:
1764
     *  - A message can only be deleted if it was sent less than 48 hours ago.
1765
     *  - Bots can delete outgoing messages in groups and supergroups.
1766
     *  - Bots granted can_post_messages permissions can delete outgoing messages in channels.
1767
     *  - If the bot is an administrator of a group, it can delete any message there.
1768
     *  - If the bot has can_delete_messages permission in a supergroup or a channel, it can delete any message there.
1769
     *
1770
     * @param int|string $chatId
1771
     * @param int $messageId
1772
     *
1773
     * @return bool
1774
     * @throws Exception
1775
     */
1776
    public function deleteMessage($chatId, $messageId)
1777
    {
1778
        return $this->call('deleteMessage', [
1779
            'chat_id' => $chatId,
1780
            'message_id' => $messageId,
1781
        ]);
1782
    }
1783
1784
    /**
1785
     * Close curl
1786
     */
1787
    public function __destruct()
1788
    {
1789
        curl_close($this->curl);
1790
    }
1791
1792
    /**
1793
     * @return string
1794
     */
1795
    public function getUrl()
1796
    {
1797
        return self::URL_PREFIX.$this->token;
1798
    }
1799
1800
    /**
1801
     * @return string
1802
     */
1803
    public function getFileUrl()
1804
    {
1805
        return self::FILE_URL_PREFIX.$this->token;
1806
    }
1807
1808
    /**
1809
     * @param Update $update
1810
     * @param string $eventName
1811
     *
1812
     * @throws Exception
1813
     *
1814
     * @return void
1815
     */
1816
    public function trackUpdate(Update $update, $eventName = 'Message')
1817
    {
1818
        if (!in_array($update->getUpdateId(), $this->trackedEvents)) {
1819
            $message = $update->getMessage();
1820
            if (!$message) {
1821
                return;
1822
            }
1823
            $this->trackedEvents[] = $update->getUpdateId();
1824
1825
            $this->track($message, $eventName);
1826
1827
            if (count($this->trackedEvents) > self::MAX_TRACKED_EVENTS) {
1828
                $this->trackedEvents = array_slice($this->trackedEvents, (int) round(self::MAX_TRACKED_EVENTS / 4));
1829
            }
1830
        }
1831
    }
1832
1833
    /**
1834
     * Wrapper for tracker
1835
     *
1836
     * @param Message $message
1837
     * @param string $eventName
1838
     *
1839
     * @throws Exception
1840
     *
1841
     * @return void
1842
     */
1843
    public function track(Message $message, $eventName = 'Message')
1844
    {
1845
        if ($this->tracker instanceof Botan) {
1846
            $this->tracker->track($message, $eventName);
1847
        }
1848
    }
1849
1850
    /**
1851
     * Use this method to send invoices. On success, the sent Message is returned.
1852
     *
1853
     * @param int|string $chatId
1854
     * @param string $title
1855
     * @param string $description
1856
     * @param string $payload
1857
     * @param string $providerToken
1858
     * @param string $startParameter
1859
     * @param string $currency
1860
     * @param array $prices
1861
     * @param bool $isFlexible
1862
     * @param string|null $photoUrl
1863
     * @param int|null $photoSize
1864
     * @param int|null $photoWidth
1865
     * @param int|null $photoHeight
1866
     * @param bool $needName
1867
     * @param bool $needPhoneNumber
1868
     * @param bool $needEmail
1869
     * @param bool $needShippingAddress
1870
     * @param int|null $replyToMessageId
1871
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
1872
     * @param bool $disableNotification
1873
     * @param string|null $providerData
1874
     * @param bool $sendPhoneNumberToProvider
1875
     * @param bool $sendEmailToProvider
1876
     * @param int|null $messageThreadId
1877
     * @param bool|null $protectContent
1878
     * @param bool|null $allowSendingWithoutReply
1879
     *
1880
     * @return Message
1881
     * @throws Exception
1882
     */
1883
    public function sendInvoice(
1884
        $chatId,
1885
        $title,
1886
        $description,
1887
        $payload,
1888
        $providerToken,
1889
        $startParameter,
1890
        $currency,
1891
        $prices,
1892
        $isFlexible = false,
1893
        $photoUrl = null,
1894
        $photoSize = null,
1895
        $photoWidth = null,
1896
        $photoHeight = null,
1897
        $needName = false,
1898
        $needPhoneNumber = false,
1899
        $needEmail = false,
1900
        $needShippingAddress = false,
1901
        $replyToMessageId = null,
1902
        $replyMarkup = null,
1903
        $disableNotification = false,
1904
        $providerData = null,
1905
        $sendPhoneNumberToProvider = false,
1906
        $sendEmailToProvider = false,
1907
        $messageThreadId = null,
1908
        $protectContent = null,
1909
        $allowSendingWithoutReply = null
1910
    ) {
1911
        return Message::fromResponse($this->call('sendInvoice', [
1912
            'chat_id' => $chatId,
1913
            'title' => $title,
1914
            'description' => $description,
1915
            'payload' => $payload,
1916
            'provider_token' => $providerToken,
1917
            'start_parameter' => $startParameter,
1918
            'currency' => $currency,
1919
            'prices' => json_encode($prices),
1920
            'is_flexible' => $isFlexible,
1921
            'photo_url' => $photoUrl,
1922
            'photo_size' => $photoSize,
1923
            'photo_width' => $photoWidth,
1924
            'photo_height' => $photoHeight,
1925
            'need_name' => $needName,
1926
            'need_phone_number' => $needPhoneNumber,
1927
            'need_email' => $needEmail,
1928
            'need_shipping_address' => $needShippingAddress,
1929
            'message_thread_id' => $messageThreadId,
1930
            'reply_to_message_id' => $replyToMessageId,
1931
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1932
            'disable_notification' => (bool) $disableNotification,
1933
            'provider_data' => $providerData,
1934
            'send_phone_number_to_provider' => (bool) $sendPhoneNumberToProvider,
1935
            'send_email_to_provider' => (bool) $sendEmailToProvider,
1936
            'protect_content' => (bool) $protectContent,
1937
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1938
        ]));
1939
    }
1940
1941
    /**
1942
     * If you sent an invoice requesting a shipping address and the parameter is_flexible was specified, the Bot API
1943
     * will send an Update with a shipping_query field to the bot. Use this method to reply to shipping queries.
1944
     * On success, True is returned.
1945
     *
1946
     * @param string $shippingQueryId
1947
     * @param bool $ok
1948
     * @param array $shippingOptions
1949
     * @param null|string $errorMessage
1950
     *
1951
     * @return bool
1952
     * @throws Exception
1953
     */
1954
    public function answerShippingQuery($shippingQueryId, $ok = true, $shippingOptions = [], $errorMessage = null)
1955
    {
1956
        return $this->call('answerShippingQuery', [
1957
            'shipping_query_id' => $shippingQueryId,
1958
            'ok' => (bool) $ok,
1959
            'shipping_options' => json_encode($shippingOptions),
1960
            'error_message' => $errorMessage
1961
        ]);
1962
    }
1963
1964
    /**
1965
     * Use this method to respond to such pre-checkout queries. On success, True is returned.
1966
     * Note: The Bot API must receive an answer within 10 seconds after the pre-checkout query was sent.
1967
     *
1968
     * @param string $preCheckoutQueryId
1969
     * @param bool $ok
1970
     * @param null|string $errorMessage
1971
     *
1972
     * @return bool
1973
     * @throws Exception
1974
     */
1975
    public function answerPreCheckoutQuery($preCheckoutQueryId, $ok = true, $errorMessage = null)
1976
    {
1977
        return $this->call('answerPreCheckoutQuery', [
1978
            'pre_checkout_query_id' => $preCheckoutQueryId,
1979
            'ok' => (bool) $ok,
1980
            'error_message' => $errorMessage
1981
        ]);
1982
    }
1983
1984
    /**
1985
     * Use this method to restrict a user in a supergroup.
1986
     * The bot must be an administrator in the supergroup for this to work and must have the appropriate admin rights.
1987
     * Pass True for all boolean parameters to lift restrictions from a user.
1988
     *
1989
     * @param string|int $chatId Unique identifier for the target chat or username of the target supergroup
1990
     *                           (in the format @supergroupusername)
1991
     * @param int $userId Unique identifier of the target user
1992
     * @param null|integer $untilDate Date when restrictions will be lifted for the user, unix time.
1993
     *                                If user is restricted for more than 366 days or less than 30 seconds from the current time,
1994
     *                                they are considered to be restricted forever
1995
     * @param bool $canSendMessages Pass True, if the user can send text messages, contacts, locations and venues
1996
     * @param bool $canSendMediaMessages No Pass True, if the user can send audios, documents, photos, videos,
1997
     *                                   video notes and voice notes, implies can_send_messages
1998
     * @param bool $canSendOtherMessages Pass True, if the user can send animations, games, stickers and
1999
     *                                   use inline bots, implies can_send_media_messages
2000
     * @param bool $canAddWebPagePreviews Pass True, if the user may add web page previews to their messages,
2001
     *                                    implies can_send_media_messages
2002
     *
2003
     * @return bool
2004
     * @throws Exception
2005
     */
2006
    public function restrictChatMember(
2007
        $chatId,
2008
        $userId,
2009
        $untilDate = null,
2010
        $canSendMessages = false,
2011
        $canSendMediaMessages = false,
2012
        $canSendOtherMessages = false,
2013
        $canAddWebPagePreviews = false
2014
    ) {
2015
        return $this->call('restrictChatMember', [
2016
            'chat_id' => $chatId,
2017
            'user_id' => $userId,
2018
            'until_date' => $untilDate,
2019
            'can_send_messages' => $canSendMessages,
2020
            'can_send_media_messages' => $canSendMediaMessages,
2021
            'can_send_other_messages' => $canSendOtherMessages,
2022
            'can_add_web_page_previews' => $canAddWebPagePreviews
2023
        ]);
2024
    }
2025
2026
    /**
2027
     * Use this method to promote or demote a user in a supergroup or a channel.
2028
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2029
     * Pass False for all boolean parameters to demote a user.
2030
     *
2031
     * @param string|int $chatId Unique identifier for the target chat or username of the target supergroup
2032
     *                           (in the format @supergroupusername)
2033
     * @param int $userId Unique identifier of the target user
2034
     * @param bool $canChangeInfo Pass True, if the administrator can change chat title, photo and other settings
2035
     * @param bool $canPostMessages Pass True, if the administrator can create channel posts, channels only
2036
     * @param bool $canEditMessages Pass True, if the administrator can edit messages of other users, channels only
2037
     * @param bool $canDeleteMessages Pass True, if the administrator can delete messages of other users
2038
     * @param bool $canInviteUsers Pass True, if the administrator can invite new users to the chat
2039
     * @param bool $canRestrictMembers Pass True, if the administrator can restrict, ban or unban chat members
2040
     * @param bool $canPinMessages Pass True, if the administrator can pin messages, supergroups only
2041
     * @param bool $canPromoteMembers Pass True, if the administrator can add new administrators with a subset of his
2042
     *                                own privileges or demote administrators that he has promoted,directly or
2043
     *                                indirectly (promoted by administrators that were appointed by him)
2044
     * @param bool $canManageTopics Pass True if the user is allowed to create, rename, close, and reopen forum topics, supergroups only
2045
     * @param bool $isAnonymous Pass True if the administrator's presence in the chat is hidden
2046
     * @return bool
2047
     *
2048
     * @throws Exception
2049
     * @throws HttpException
2050
     * @throws InvalidJsonException
2051
     */
2052
    public function promoteChatMember(
2053
        $chatId,
2054
        $userId,
2055
        $canChangeInfo = true,
2056
        $canPostMessages = true,
2057
        $canEditMessages = true,
2058
        $canDeleteMessages = true,
2059
        $canInviteUsers = true,
2060
        $canRestrictMembers = true,
2061
        $canPinMessages = true,
2062
        $canPromoteMembers = true,
2063
        $canManageTopics = true,
2064
        $isAnonymous = false
2065
    ) {
2066
        return $this->call('promoteChatMember', [
2067
            'chat_id' => $chatId,
2068
            'user_id' => $userId,
2069
            'is_anonymous' => $isAnonymous,
2070
            'can_change_info' => $canChangeInfo,
2071
            'can_post_messages' => $canPostMessages,
2072
            'can_edit_messages' => $canEditMessages,
2073
            'can_delete_messages' => $canDeleteMessages,
2074
            'can_invite_users' => $canInviteUsers,
2075
            'can_restrict_members' => $canRestrictMembers,
2076
            'can_pin_messages' => $canPinMessages,
2077
            'can_promote_members' => $canPromoteMembers,
2078
            'can_manage_topics' => $canManageTopics
2079
        ]);
2080
    }
2081
2082
    /**
2083
     * Use this method to export an invite link to a supergroup or a channel.
2084
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2085
     *
2086
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2087
     *                           (in the format @channelusername)
2088
     * @return string
2089
     * @throws Exception
2090
     */
2091
    public function exportChatInviteLink($chatId)
2092
    {
2093
        return $this->call('exportChatInviteLink', [
2094
            'chat_id' => $chatId
2095
        ]);
2096
    }
2097
2098
    /**
2099
     * Use this method to set a new profile photo for the chat. Photos can't be changed for private chats.
2100
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2101
     *
2102
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2103
     *                           (in the format @channelusername)
2104
     * @param \CURLFile|string $photo New chat photo, uploaded using multipart/form-data
2105
     *
2106
     * @return bool
2107
     * @throws Exception
2108
     */
2109
    public function setChatPhoto($chatId, $photo)
2110
    {
2111
        return $this->call('setChatPhoto', [
2112
            'chat_id' => $chatId,
2113
            'photo' => $photo
2114
        ]);
2115
    }
2116
2117
    /**
2118
     * Use this method to delete a chat photo. Photos can't be changed for private chats.
2119
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2120
     *
2121
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2122
     *                           (in the format @channelusername)
2123
     *
2124
     * @return bool
2125
     * @throws Exception
2126
     */
2127
    public function deleteChatPhoto($chatId)
2128
    {
2129
        return $this->call('deleteChatPhoto', [
2130
            'chat_id' => $chatId
2131
        ]);
2132
    }
2133
2134
    /**
2135
     * Use this method to change the title of a chat. Titles can't be changed for private chats.
2136
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2137
     *
2138
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2139
     *                           (in the format @channelusername)
2140
     * @param string $title New chat title, 1-255 characters
2141
     *
2142
     * @return bool
2143
     * @throws Exception
2144
     */
2145
    public function setChatTitle($chatId, $title)
2146
    {
2147
        return $this->call('setChatTitle', [
2148
            'chat_id' => $chatId,
2149
            'title' => $title
2150
        ]);
2151
    }
2152
2153
    /**
2154
     * Use this method to change the description of a supergroup or a channel.
2155
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2156
     *
2157
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2158
     *                           (in the format @channelusername)
2159
     * @param string|null $description New chat description, 0-255 characters
2160
     *
2161
     * @return bool
2162
     * @throws Exception
2163
     */
2164
    public function setChatDescription($chatId, $description = null)
2165
    {
2166
        return $this->call('setChatDescription', [
2167
            'chat_id' => $chatId,
2168
            'title' => $description
2169
        ]);
2170
    }
2171
2172
    /**
2173
     * Use this method to pin a message in a supergroup.
2174
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2175
     *
2176
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2177
     *                           (in the format @channelusername)
2178
     * @param int $messageId Identifier of a message to pin
2179
     * @param bool $disableNotification
2180
     *
2181
     * @return bool
2182
     * @throws Exception
2183
     */
2184
    public function pinChatMessage($chatId, $messageId, $disableNotification = false)
2185
    {
2186
        return $this->call('pinChatMessage', [
2187
            'chat_id' => $chatId,
2188
            'message_id' => $messageId,
2189
            'disable_notification' => $disableNotification
2190
        ]);
2191
    }
2192
2193
    /**
2194
     * Use this method to unpin a message in a supergroup chat.
2195
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2196
     *
2197
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2198
     *                           (in the format @channelusername)
2199
     * @param int|null $messageId Identifier of a message to pin (optional)
2200
     *
2201
     * @return bool
2202
     * @throws Exception
2203
     */
2204
    public function unpinChatMessage($chatId, $messageId = null)
2205
    {
2206
        return $this->call('unpinChatMessage', [
2207
            'chat_id' => $chatId,
2208
            'message_id' => $messageId,
2209
        ]);
2210
    }
2211
2212
    /**
2213
     * Use this method to get up to date information about the chat
2214
     * (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.).
2215
     *
2216
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2217
     *                           (in the format @channelusername)
2218
     *
2219
     * @return Chat
2220
     * @throws Exception
2221
     */
2222
    public function getChat($chatId)
2223
    {
2224
        return Chat::fromResponse($this->call('getChat', [
2225
            'chat_id' => $chatId
2226
        ]));
2227
    }
2228
2229
    /**
2230
     * Use this method to get information about a member of a chat.
2231
     *
2232
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2233
     *                           (in the format @channelusername)
2234
     * @param int $userId
2235
     *
2236
     * @return ChatMember
2237
     * @throws Exception
2238
     */
2239
    public function getChatMember($chatId, $userId)
2240
    {
2241
        return ChatMember::fromResponse($this->call('getChatMember', [
2242
            'chat_id' => $chatId,
2243
            'user_id' => $userId
2244
        ]));
2245
    }
2246
2247
    /**
2248
     * Use this method for your bot to leave a group, supergroup or channel.
2249
     *
2250
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2251
     *                           (in the format @channelusername)
2252
     *
2253
     * @return bool
2254
     * @throws Exception
2255
     */
2256
    public function leaveChat($chatId)
2257
    {
2258
        return $this->call('leaveChat', [
2259
            'chat_id' => $chatId
2260
        ]);
2261
    }
2262
2263
    /**
2264
     * Use this method to get the number of members in a chat.
2265
     *
2266
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2267
     *                           (in the format @channelusername)
2268
     *
2269
     * @return int
2270
     * @throws Exception
2271
     */
2272
    public function getChatMembersCount($chatId)
2273
    {
2274
        return $this->call(
2275
            'getChatMembersCount',
2276
            [
2277
                'chat_id' => $chatId
2278
            ]
2279
        );
2280
    }
2281
2282
    /**
2283
     * Use this method to get a list of administrators in a chat.
2284
     *
2285
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2286
     *                           (in the format @channelusername)
2287
     *
2288
     * @return ChatMember[]
2289
     * @throws InvalidArgumentException
2290
     * @throws Exception
2291
     */
2292
    public function getChatAdministrators($chatId)
2293
    {
2294
        return ArrayOfChatMemberEntity::fromResponse(
2295
            $this->call(
2296
                'getChatAdministrators',
2297
                [
2298
                    'chat_id' => $chatId
2299
                ]
2300
            )
2301
        );
2302
    }
2303
2304
    /**
2305
     * As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1 minute long.
2306
     * Use this method to send video messages.
2307
     * On success, the sent Message is returned.
2308
     *
2309
     * @param int|string $chatId chat_id or @channel_name
2310
     * @param \CURLFile|string $videoNote
2311
     * @param int|null $duration
2312
     * @param int|null $length
2313
     * @param int|null $replyToMessageId
2314
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
2315
     * @param bool $disableNotification
2316
     * @param int|null $messageThreadId
2317
     * @param bool|null $protectContent
2318
     * @param bool|null $allowSendingWithoutReply
2319
     * @param \CURLFile|\CURLStringFile|string|null $thumbnail
2320
     *
2321
     * @return Message
2322
     * @throws InvalidArgumentException
2323
     * @throws Exception
2324
     */
2325
    public function sendVideoNote(
2326
        $chatId,
2327
        $videoNote,
2328
        $duration = null,
2329
        $length = null,
2330
        $replyToMessageId = null,
2331
        $replyMarkup = null,
2332
        $disableNotification = false,
2333
        $messageThreadId = null,
2334
        $protectContent = null,
2335
        $allowSendingWithoutReply = null,
2336
        $thumbnail = null
2337
    ) {
2338
        return Message::fromResponse($this->call('sendVideoNote', [
2339
            'chat_id' => $chatId,
2340
            'video_note' => $videoNote,
2341
            'duration' => $duration,
2342
            'length' => $length,
2343
            'message_thread_id' => $messageThreadId,
2344
            'reply_to_message_id' => $replyToMessageId,
2345
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
2346
            'disable_notification' => (bool) $disableNotification,
2347
            'protect_content' => (bool) $protectContent,
2348
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
2349
            'thumbnail' => $thumbnail,
2350
        ]));
2351
    }
2352
2353
    /**
2354
     * Use this method to send a group of photos or videos as an album.
2355
     * On success, the sent \TelegramBot\Api\Types\Message is returned.
2356
     *
2357
     * @param int|string $chatId
2358
     * @param ArrayOfInputMedia $media
2359
     * @param bool $disableNotification
2360
     * @param int|null $replyToMessageId
2361
     * @param int|null $messageThreadId
2362
     * @param bool|null $protectContent
2363
     * @param bool|null $allowSendingWithoutReply
2364
     * @param array<string, \CURLFile|\CURLStringFile> $attachments Attachments to use in attach://<attachment>
2365
     *
2366
     * @return Message[]
2367
     * @throws Exception
2368
     */
2369
    public function sendMediaGroup(
2370
        $chatId,
2371
        $media,
2372
        $disableNotification = false,
2373
        $replyToMessageId = null,
2374
        $messageThreadId = null,
2375
        $protectContent = null,
2376
        $allowSendingWithoutReply = null,
2377
        $attachments = []
2378
    ) {
2379
        return ArrayOfMessages::fromResponse($this->call('sendMediaGroup', [
2380
            'chat_id' => $chatId,
2381
            'media' => $media->toJson(),
2382
            'message_thread_id' => $messageThreadId,
2383
            'reply_to_message_id' => (int) $replyToMessageId,
2384
            'disable_notification' => (bool) $disableNotification,
2385
            'protect_content' => (bool) $protectContent,
2386
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
2387
        ] + $attachments));
2388
    }
2389
2390
    /**
2391
     * Enable proxy for curl requests. Empty string will disable proxy.
2392
     *
2393
     * @param string $proxyString
2394
     * @param bool $socks5
2395
     *
2396
     * @return BotApi
2397
     */
2398
    public function setProxy($proxyString = '', $socks5 = false)
2399
    {
2400
        if (empty($proxyString)) {
2401
            $this->proxySettings = [];
2402
            return $this;
2403
        }
2404
2405
        $this->proxySettings = [
2406
            CURLOPT_PROXY => $proxyString,
2407
            CURLOPT_HTTPPROXYTUNNEL => true,
2408
        ];
2409
2410
        if ($socks5) {
2411
            $this->proxySettings[CURLOPT_PROXYTYPE] = CURLPROXY_SOCKS5;
2412
        }
2413
        return $this;
2414
    }
2415
2416
    /**
2417
     * Use this method to send a native poll. A native poll can't be sent to a private chat.
2418
     * On success, the sent \TelegramBot\Api\Types\Message is returned.
2419
     *
2420
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2421
     *                           (in the format @channelusername)
2422
     * @param string $question Poll question, 1-255 characters
2423
     * @param array $options A JSON-serialized list of answer options, 2-10 strings 1-100 characters each
2424
     * @param bool $isAnonymous True, if the poll needs to be anonymous, defaults to True
2425
     * @param string|null $type Poll type, “quiz” or “regular”, defaults to “regular”
2426
     * @param bool $allowsMultipleAnswers True, if the poll allows multiple answers,
2427
     *                                    ignored for polls in quiz mode, defaults to False
2428
     * @param string|null $correctOptionId 0-based identifier of the correct answer option, required for polls in quiz mode
2429
     * @param bool $isClosed Pass True, if the poll needs to be immediately closed. This can be useful for poll preview.
2430
     * @param bool $disableNotification Sends the message silently. Users will receive a notification with no sound.
2431
     * @param int|null $replyToMessageId If the message is a reply, ID of the original message
2432
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup Additional interface options. A JSON-serialized object for an inline keyboard,
2433
     *                                                                                                  custom reply keyboard, instructions to remove reply
2434
     *                                                                                                  keyboard or to force a reply from the user.
2435
     * @param int|null $messageThreadId Unique identifier for the target message thread (topic) of the forum; for forum supergroups only
2436
     * @param bool|null $protectContent
2437
     * @param bool|null $allowSendingWithoutReply
2438
     *
2439
     * @return Message
2440
     * @throws Exception
2441
     * @throws HttpException
2442
     * @throws InvalidJsonException
2443
     */
2444
    public function sendPoll(
2445
        $chatId,
2446
        $question,
2447
        $options,
2448
        $isAnonymous = false,
2449
        $type = null,
2450
        $allowsMultipleAnswers = false,
2451
        $correctOptionId = null,
2452
        $isClosed = false,
2453
        $disableNotification = false,
2454
        $replyToMessageId = null,
2455
        $replyMarkup = null,
2456
        $messageThreadId = null,
2457
        $protectContent = null,
2458
        $allowSendingWithoutReply = null
2459
    ) {
2460
        return Message::fromResponse($this->call('sendPoll', [
2461
            'chat_id' => $chatId,
2462
            'question' => $question,
2463
            'options' => json_encode($options),
2464
            'is_anonymous' => (bool) $isAnonymous,
2465
            'type' => (string) $type,
2466
            'allows_multiple_answers' => (bool) $allowsMultipleAnswers,
2467
            'correct_option_id' => (int) $correctOptionId,
2468
            'is_closed' => (bool) $isClosed,
2469
            'disable_notification' => (bool) $disableNotification,
2470
            'message_thread_id' => $messageThreadId,
2471
            'reply_to_message_id' => (int) $replyToMessageId,
2472
            'reply_markup' => $replyMarkup === null ? $replyMarkup : $replyMarkup->toJson(),
2473
            'protect_content' => (bool) $protectContent,
2474
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
2475
        ]));
2476
    }
2477
2478
    /**
2479
     * Use this method to send a dice, which will have a random value from 1 to 6.
2480
     * On success, the sent Message is returned. (Yes, we're aware of the “proper” singular of die.
2481
     * But it's awkward, and we decided to help it change. One dice at a time!)
2482
     *
2483
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2484
     *                           (in the format @channelusername)
2485
     * @param string $emoji Emoji on which the dice throw animation is based. Currently, must be one of “🎲”,
2486
     *                      “🎯”, “🏀”, “⚽”, or “🎰”. Dice can have values 1-6 for “🎲” and “🎯”, values 1-5 for “🏀” and “⚽”, and
2487
     *                      values 1-64 for “🎰”. Defaults to “🎲
2488
     * @param bool $disableNotification Sends the message silently. Users will receive a notification with no sound.
2489
     * @param string|null $replyToMessageId If the message is a reply, ID of the original message
2490
     * @param bool $allowSendingWithoutReply Pass True, if the message should be sent even if the specified replied-to
2491
     *                                       message is not found,
2492
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup Additional interface options. A JSON-serialized object for an inline keyboard,
2493
     *                                                                                                  custom reply keyboard, instructions to remove reply
2494
     *                                                                                                  keyboard or to force a reply from the user.
2495
     * @param int|null $messageThreadId
2496
     * @param bool|null $protectContent
2497
     *
2498
     * @return Message
2499
     * @throws Exception
2500
     * @throws HttpException
2501
     * @throws InvalidJsonException
2502
     */
2503
    public function sendDice(
2504
        $chatId,
2505
        $emoji,
2506
        $disableNotification = false,
2507
        $replyToMessageId = null,
2508
        $allowSendingWithoutReply = false,
2509
        $replyMarkup = null,
2510
        $messageThreadId = null,
2511
        $protectContent = null
2512
    ) {
2513
        return Message::fromResponse($this->call('sendDice', [
2514
            'chat_id' => $chatId,
2515
            'emoji' => $emoji,
2516
            'disable_notification' => (bool) $disableNotification,
2517
            'message_thread_id' => $messageThreadId,
2518
            'reply_to_message_id' => (int) $replyToMessageId,
2519
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
2520
            'reply_markup' => $replyMarkup === null ? $replyMarkup : $replyMarkup->toJson(),
2521
            'protect_content' => (bool) $protectContent,
2522
        ]));
2523
    }
2524
2525
    /**
2526
     * Use this method to stop a poll which was sent by the bot.
2527
     * On success, the stopped \TelegramBot\Api\Types\Poll with the final results is returned.
2528
     *
2529
     * @param int|string $chatId
2530
     * @param int $messageId
2531
     * @param InlineKeyboardMarkup|null $replyMarkup
2532
     * @return Poll
2533
     * @throws InvalidArgumentException
2534
     * @throws Exception
2535
     */
2536
    public function stopPoll(
2537
        $chatId,
2538
        $messageId,
2539
        $replyMarkup = null
2540
    ) {
2541
        return Poll::fromResponse($this->call('stopPoll', [
2542
            'chat_id' => $chatId,
2543
            'message_id' => $messageId,
2544
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
2545
        ]));
2546
    }
2547
2548
    /**
2549
     * Use this method to create a topic in a forum supergroup chat.
2550
     * The bot must be an administrator in the chat for this to work
2551
     * and must have the can_manage_topics administrator rights.
2552
     * Returns information about the created topic as a ForumTopic object.
2553
     *
2554
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2555
     * @param string $name Topic name, 1-128 characters
2556
     * @param int $iconColor Color of the topic icon in RGB format.
2557
     *                       Currently, must be one of 7322096 (0x6FB9F0), 16766590 (0xFFD67E), 13338331 (0xCB86DB),
2558
     *                       9367192 (0x8EEE98), 16749490 (0xFF93B2), or 16478047 (0xFB6F5F)
2559
     * @param int|null $iconCustomEmojiId Unique identifier of the custom emoji shown as the topic icon.
2560
     *                                    Use getForumTopicIconStickers to get all allowed custom emoji identifiers.
2561
     *
2562
     * @return ForumTopic
2563
     *
2564
     * @throws Exception
2565
     *
2566
     * @author bernard-ng <[email protected]>
2567
     */
2568
    public function createForumTopic(
2569
        $chatId,
2570
        $name,
2571
        $iconColor,
2572
        $iconCustomEmojiId = null
2573
    ) {
2574
        return ForumTopic::fromResponse($this->call('createForumTopic', [
2575
            'chat_id' => $chatId,
2576
            'name' => $name,
2577
            'icon_color' => $iconColor,
2578
            'icon_custom_emoji_id' => $iconCustomEmojiId,
2579
        ]));
2580
    }
2581
2582
    /**
2583
     * Use this method to edit name and icon of a topic in a forum supergroup chat.
2584
     * The bot must be an administrator in the chat for this to work and must have can_manage_topics administrator rights,
2585
     * unless it is the creator of the topic. Returns True on success.
2586
     *
2587
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2588
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2589
     * @param string $name Topic name, 1-128 characters
2590
     * @param int|null $iconCustomEmojiId Unique identifier of the custom emoji shown as the topic icon.
2591
     *                                    Use getForumTopicIconStickers to get all allowed custom emoji identifiers.
2592
     *
2593
     * @return bool
2594
     * @throws Exception
2595
     *
2596
     * @author bernard-ng <[email protected]>
2597
     */
2598
    public function editForumTopic(
2599
        $chatId,
2600
        $messageThreadId,
2601
        $name,
2602
        $iconCustomEmojiId = null
2603
    ) {
2604
        return $this->call('editForumTopic', [
2605
            'chat_id' => $chatId,
2606
            'message_thread_id' => $messageThreadId,
2607
            'name' => $name,
2608
            'icon_custom_emoji_id' => $iconCustomEmojiId,
2609
        ]);
2610
    }
2611
2612
    /**
2613
     * Use this method to delete a topic in a forum supergroup chat.
2614
     * The bot must be an administrator in the chat for this to work and must have can_manage_topics administrator rights,
2615
     * unless it is the creator of the topic. Returns True on success.
2616
     *
2617
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2618
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2619
     *
2620
     * @return bool
2621
     * @throws Exception
2622
     *
2623
     * @author bernard-ng <[email protected]>
2624
     */
2625
    public function closeForumTopic($chatId, $messageThreadId)
2626
    {
2627
        return $this->call('closeForumTopic', [
2628
            'chat_id' => $chatId,
2629
            'message_thread_id' => $messageThreadId,
2630
        ]);
2631
    }
2632
2633
    /**
2634
     * Use this method to reopen a closed topic in a forum supergroup chat.
2635
     * The bot must be an administrator in the chat for this to work and must have the can_manage_topics administrator rights,
2636
     * unless it is the creator of the topic. Returns True on success.
2637
     *
2638
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2639
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2640
     *
2641
     * @return bool
2642
     * @throws Exception
2643
     *
2644
     * @author bernard-ng <[email protected]>
2645
     */
2646
    public function reopenForumTopic($chatId, $messageThreadId)
2647
    {
2648
        return $this->call('reopenForumTopic', [
2649
            'chat_id' => $chatId,
2650
            'message_thread_id' => $messageThreadId,
2651
        ]);
2652
    }
2653
2654
    /**
2655
     * Use this method to delete a forum topic along with all its messages in a forum supergroup chat.
2656
     * The bot must be an administrator in the chat for this to work and must have the can_delete_messages administrator rights.
2657
     * Returns True on success.
2658
     *
2659
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2660
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2661
     *
2662
     * @return bool
2663
     * @throws Exception
2664
     *
2665
     * @author bernard-ng <[email protected]>
2666
     */
2667
    public function deleteForumTopic($chatId, $messageThreadId)
2668
    {
2669
        return $this->call('deleteForumTopic', [
2670
            'chat_id' => $chatId,
2671
            'message_thread_id' => $messageThreadId,
2672
        ]);
2673
    }
2674
2675
    /**
2676
     * Use this method to clear the list of pinned messages in a forum topic.
2677
     * The bot must be an administrator in the chat for this to work and must have the can_pin_messages administrator right in the supergroup.
2678
     * Returns True on success.
2679
     *
2680
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2681
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2682
     *
2683
     * @return bool
2684
     * @throws Exception
2685
     *
2686
     * @author bernard-ng <[email protected]>
2687
     */
2688
    public function unpinAllForumTopicMessages($chatId, $messageThreadId)
2689
    {
2690
        return $this->call('unpinAllForumTopicMessages', [
2691
            'chat_id' => $chatId,
2692
            'message_thread_id' => $messageThreadId,
2693
        ]);
2694
    }
2695
2696
    /**
2697
     * Use this method to get custom emoji stickers, which can be used as a forum topic icon by any user.
2698
     * Requires no parameters. Returns an Array of Sticker objects.
2699
     *
2700
     * @return Sticker[]
2701
     * @throws Exception
2702
     *
2703
     * @author bernard-ng <[email protected]>
2704
     */
2705
    public function getForumTopicIconStickers()
2706
    {
2707
        return ArrayOfSticker::fromResponse($this->call('getForumTopicIconStickers'));
2708
    }
2709
2710
    /**
2711
     * @param string $webAppQueryId
2712
     * @param AbstractInlineQueryResult $result
2713
     * @return SentWebAppMessage
2714
     * @throws Exception
2715
     * @throws HttpException
2716
     * @throws InvalidArgumentException
2717
     * @throws InvalidJsonException
2718
     */
2719
    public function answerWebAppQuery($webAppQueryId, $result)
2720
    {
2721
        return SentWebAppMessage::fromResponse($this->call('answerWebAppQuery', [
2722
            'web_app_query_id' => $webAppQueryId,
2723
            'result' => $result->toJson(),
2724
        ]));
2725
    }
2726
2727
    /**
2728
     * Set an option for a cURL transfer
2729
     *
2730
     * @param int $option The CURLOPT_XXX option to set
2731
     * @param mixed $value The value to be set on option
2732
     *
2733
     * @return void
2734
     */
2735
    public function setCurlOption($option, $value)
2736
    {
2737
        $this->customCurlOptions[$option] = $value;
2738
    }
2739
2740
    /**
2741
     * Unset an option for a cURL transfer
2742
     *
2743
     * @param int $option The CURLOPT_XXX option to unset
2744
     *
2745
     * @return void
2746
     */
2747
    public function unsetCurlOption($option)
2748
    {
2749
        unset($this->customCurlOptions[$option]);
2750
    }
2751
2752
    /**
2753
     * Clean custom options
2754
     *
2755
     * @return void
2756
     */
2757
    public function resetCurlOptions()
2758
    {
2759
        $this->customCurlOptions = [];
2760
    }
2761
}
2762