Completed
Push — master ( 2a7614...8b5c55 )
by Alexander
03:27 queued 03:25
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
        @trigger_error(sprintf('Method "%s::%s" is deprecated. Use "banChatMember"', __CLASS__, __METHOD__), \E_USER_DEPRECATED);
1519
1520
        return $this->call('kickChatMember', [
1521
            'chat_id' => $chatId,
1522
            'user_id' => $userId,
1523
            'until_date' => $untilDate
1524
        ]);
1525
    }
1526
1527
    /**
1528
     * Use this method to ban a user in a group, a supergroup or a channel. In the case of supergroups and channels,
1529
     * the user will not be able to return to the chat on their own using invite links, etc., unless unbanned first.
1530
     * The bot must be an administrator in the chat for this to work and must have the appropriate administrator rights.
1531
     * Returns True on success.
1532
     *
1533
     * @param int|string $chatId Unique identifier for the target group or username of the
1534
     *                           target supergroup or channel (in the format @channelusername)
1535
     * @param int $userId Unique identifier of the target user
1536
     * @param null|int $untilDate Date when the user will be unbanned, unix time.
1537
     *                            If user is banned for more than 366 days or less than 30 seconds from the current time they are considered to be banned forever.
1538
     *                            Applied for supergroups and channels only.
1539
     * @param bool|null $revokeMessages Pass True to delete all messages from the chat for the user that is being removed.
1540
     *                                  If False, the user will be able to see messages in the group that were sent before the user was removed.
1541
     *                                  Always True for supergroups and channels.
1542
     *
1543
     * @return bool
1544
     * @throws Exception
1545
     */
1546
    public function banChatMember($chatId, $userId, $untilDate = null, $revokeMessages = null)
1547
    {
1548
        return $this->call('banChatMember', [
1549
            'chat_id' => $chatId,
1550
            'user_id' => $userId,
1551
            'until_date' => $untilDate,
1552
            'revoke_messages' => $revokeMessages,
1553
        ]);
1554
    }
1555
1556
    /**
1557
     * Use this method to unban a previously kicked user in a supergroup.
1558
     * The user will not return to the group automatically, but will be able to join via link, etc.
1559
     * The bot must be an administrator in the group for this to work. Returns True on success.
1560
     *
1561
     * @param int|string $chatId Unique identifier for the target group
1562
     *                           or username of the target supergroup (in the format @supergroupusername)
1563
     * @param int $userId Unique identifier of the target user
1564
     *
1565
     * @return bool
1566
     * @throws Exception
1567
     */
1568
    public function unbanChatMember($chatId, $userId)
1569
    {
1570
        return $this->call('unbanChatMember', [
1571
            'chat_id' => $chatId,
1572
            'user_id' => $userId,
1573
        ]);
1574
    }
1575
1576
    /**
1577
     * Use this method to send answers to callback queries sent from inline keyboards.
1578
     * The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.
1579
     *
1580
     * @param string $callbackQueryId
1581
     * @param string|null $text
1582
     * @param bool $showAlert
1583
     * @param string|null $url
1584
     * @param int $cacheTime
1585
     *
1586
     * @return bool
1587
     * @throws Exception
1588
     */
1589
    public function answerCallbackQuery($callbackQueryId, $text = null, $showAlert = false, $url = null, $cacheTime = 0)
1590
    {
1591
        return $this->call('answerCallbackQuery', [
1592
            'callback_query_id' => $callbackQueryId,
1593
            'text' => $text,
1594
            'show_alert' => (bool) $showAlert,
1595
            'url' => $url,
1596
            'cache_time' => $cacheTime
1597
        ]);
1598
    }
1599
1600
    /**
1601
     * Use this method to change the list of the bot's commands. Returns True on success.
1602
     *
1603
     * @param ArrayOfBotCommand|BotCommand[] $commands
1604
     * @param string|null $scope
1605
     * @param string|null $languageCode
1606
     *
1607
     * @return mixed
1608
     * @throws Exception
1609
     * @throws HttpException
1610
     * @throws InvalidJsonException
1611 9
     */
1612
    public function setMyCommands($commands, $scope = null, $languageCode = null)
1613 9
    {
1614 9
        if (!$commands instanceof ArrayOfBotCommand) {
1615
            @trigger_error(sprintf('Passing array of BotCommand to "%s::%s" is deprecated. Use %s', __CLASS__, __METHOD__, ArrayOfBotCommand::class), \E_USER_DEPRECATED);
1616
            $commands = new ArrayOfBotCommand($commands);
1617
        }
1618
1619
        return $this->call('setMyCommands', [
1620
            'commands' => $commands->toJson(),
1621
            'scope' => $scope,
1622
            'language_code' => $languageCode,
1623
        ]);
1624
    }
1625
1626
    /**
1627
     * Use this method to get the current list of the bot's commands. Requires no parameters.
1628
     * Returns Array of BotCommand on success.
1629
     *
1630
     * @return ArrayOfBotCommand
1631
     *
1632
     * @throws Exception
1633
     * @throws HttpException
1634
     * @throws InvalidJsonException
1635
     */
1636
    public function getMyCommands()
1637
    {
1638
        return ArrayOfBotCommand::fromResponse($this->call('getMyCommands'));
1639
    }
1640
1641
    /**
1642
     * Use this method to edit text messages sent by the bot or via the bot
1643
     * On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned.
1644
     *
1645
     * @param int|string $chatId
1646
     * @param int $messageId
1647
     * @param string $text
1648
     * @param string $inlineMessageId
1649
     * @param string|null $parseMode
1650
     * @param bool $disablePreview
1651
     * @param InlineKeyboardMarkup|null $replyMarkup
1652
     *
1653
     * @return Message|true
1654
     * @throws Exception
1655
     */
1656
    public function editMessageText(
1657
        $chatId,
1658
        $messageId,
1659
        $text,
1660
        $parseMode = null,
1661
        $disablePreview = false,
1662
        $replyMarkup = null,
1663
        $inlineMessageId = null
1664
    ) {
1665
        $response = $this->call('editMessageText', [
1666
            'chat_id' => $chatId,
1667
            'message_id' => $messageId,
1668
            'text' => $text,
1669
            'inline_message_id' => $inlineMessageId,
1670
            'parse_mode' => $parseMode,
1671
            'disable_web_page_preview' => $disablePreview,
1672
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1673
        ]);
1674
        if ($response === true) {
1675
            return true;
1676
        }
1677
1678
        return Message::fromResponse($response);
1679
    }
1680
1681
    /**
1682
     * Use this method to edit text messages sent by the bot or via the bot
1683
     * On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned.
1684
     *
1685
     * @param int|string $chatId
1686
     * @param int $messageId
1687
     * @param string|null $caption
1688
     * @param InlineKeyboardMarkup|null $replyMarkup
1689
     * @param string $inlineMessageId
1690
     * @param string|null $parseMode
1691
     *
1692
     * @return Message|true
1693
     * @throws InvalidArgumentException
1694
     * @throws Exception
1695
     */
1696
    public function editMessageCaption(
1697
        $chatId,
1698
        $messageId,
1699
        $caption = null,
1700
        $replyMarkup = null,
1701
        $inlineMessageId = null,
1702
        $parseMode = null
1703
    ) {
1704
        $response = $this->call('editMessageCaption', [
1705
            'chat_id' => $chatId,
1706
            'message_id' => $messageId,
1707
            'inline_message_id' => $inlineMessageId,
1708
            'caption' => $caption,
1709
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1710
            'parse_mode' => $parseMode
1711
        ]);
1712
        if ($response === true) {
1713
            return true;
1714
        }
1715
1716
        return Message::fromResponse($response);
1717
    }
1718
1719
    /**
1720
     * Use this method to edit animation, audio, document, photo, or video messages.
1721
     * If a message is a part of a message album, then it can be edited only to a photo or a video.
1722
     * Otherwise, message type can be changed arbitrarily.
1723
     * When inline message is edited, new file can't be uploaded.
1724
     * Use previously uploaded file via its file_id or specify a URL.
1725
     * On success, if the edited message was sent by the bot, the edited Message is returned, otherwise True is returned
1726
     *
1727
     * @param string $chatId
1728
     * @param string $messageId
1729
     * @param InputMedia $media
1730
     * @param string|null $inlineMessageId
1731
     * @param InlineKeyboardMarkup|null $replyMarkup
1732
     * @param array<string, \CURLFile|\CURLStringFile> $attachments Attachments to use in attach://<attachment>
1733
     *
1734
     * @return Message|true
1735
     *
1736
     * @throws Exception
1737
     * @throws HttpException
1738
     * @throws InvalidJsonException
1739
     */
1740
    public function editMessageMedia(
1741
        $chatId,
1742
        $messageId,
1743
        InputMedia $media,
1744
        $inlineMessageId = null,
1745
        $replyMarkup = null,
1746
        $attachments = []
1747
    ) {
1748
        $response = $this->call('editMessageMedia', [
1749
            'chat_id' => $chatId,
1750
            'message_id' => $messageId,
1751
            'inline_message_id' => $inlineMessageId,
1752
            'media' => $media->toJson(),
1753
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1754
        ] + $attachments);
1755
        if ($response === true) {
1756
            return true;
1757
        }
1758
1759
        return Message::fromResponse($response);
1760
    }
1761
1762
    /**
1763
     * Use this method to edit only the reply markup of messages sent by the bot or via the bot
1764
     * On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned.
1765
     *
1766
     * @param int|string $chatId
1767
     * @param int $messageId
1768
     * @param InlineKeyboardMarkup|null $replyMarkup
1769
     * @param string $inlineMessageId
1770
     *
1771
     * @return Message|true
1772
     * @throws Exception
1773
     */
1774
    public function editMessageReplyMarkup(
1775
        $chatId,
1776
        $messageId,
1777
        $replyMarkup = null,
1778
        $inlineMessageId = null
1779
    ) {
1780
        $response = $this->call('editMessageReplyMarkup', [
1781
            'chat_id' => $chatId,
1782
            'message_id' => $messageId,
1783
            'inline_message_id' => $inlineMessageId,
1784
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1785
        ]);
1786
        if ($response === true) {
1787
            return true;
1788
        }
1789
1790
        return Message::fromResponse($response);
1791
    }
1792
1793
    /**
1794
     * Use this method to delete a message, including service messages, with the following limitations:
1795
     *  - A message can only be deleted if it was sent less than 48 hours ago.
1796
     *  - Bots can delete outgoing messages in groups and supergroups.
1797
     *  - Bots granted can_post_messages permissions can delete outgoing messages in channels.
1798
     *  - If the bot is an administrator of a group, it can delete any message there.
1799
     *  - If the bot has can_delete_messages permission in a supergroup or a channel, it can delete any message there.
1800
     *
1801
     * @param int|string $chatId
1802
     * @param int $messageId
1803
     *
1804
     * @return bool
1805
     * @throws Exception
1806
     */
1807
    public function deleteMessage($chatId, $messageId)
1808
    {
1809
        return $this->call('deleteMessage', [
1810
            'chat_id' => $chatId,
1811
            'message_id' => $messageId,
1812
        ]);
1813
    }
1814
1815
    /**
1816
     * Close curl
1817
     */
1818
    public function __destruct()
1819
    {
1820
        curl_close($this->curl);
1821
    }
1822
1823
    /**
1824
     * @return string
1825
     */
1826
    public function getUrl()
1827
    {
1828
        return self::URL_PREFIX.$this->token;
1829
    }
1830
1831
    /**
1832
     * @return string
1833
     */
1834
    public function getFileUrl()
1835
    {
1836
        return self::FILE_URL_PREFIX.$this->token;
1837
    }
1838
1839
    /**
1840
     * @param Update $update
1841
     * @param string $eventName
1842
     *
1843
     * @throws Exception
1844
     *
1845
     * @return void
1846
     */
1847
    public function trackUpdate(Update $update, $eventName = 'Message')
1848
    {
1849
        if (!in_array($update->getUpdateId(), $this->trackedEvents)) {
1850
            $message = $update->getMessage();
1851
            if (!$message) {
1852
                return;
1853
            }
1854
            $this->trackedEvents[] = $update->getUpdateId();
1855
1856
            $this->track($message, $eventName);
1857
1858
            if (count($this->trackedEvents) > self::MAX_TRACKED_EVENTS) {
1859
                $this->trackedEvents = array_slice($this->trackedEvents, (int) round(self::MAX_TRACKED_EVENTS / 4));
1860
            }
1861
        }
1862
    }
1863
1864
    /**
1865
     * Wrapper for tracker
1866
     *
1867
     * @param Message $message
1868
     * @param string $eventName
1869
     *
1870
     * @throws Exception
1871
     *
1872
     * @return void
1873
     */
1874
    public function track(Message $message, $eventName = 'Message')
1875
    {
1876
        if ($this->tracker instanceof Botan) {
1877
            $this->tracker->track($message, $eventName);
1878
        }
1879
    }
1880
1881
    /**
1882
     * Use this method to send invoices. On success, the sent Message is returned.
1883
     *
1884
     * @param int|string $chatId
1885
     * @param string $title
1886
     * @param string $description
1887
     * @param string $payload
1888
     * @param string $providerToken
1889
     * @param string $startParameter
1890
     * @param string $currency
1891
     * @param array $prices
1892
     * @param bool $isFlexible
1893
     * @param string|null $photoUrl
1894
     * @param int|null $photoSize
1895
     * @param int|null $photoWidth
1896
     * @param int|null $photoHeight
1897
     * @param bool $needName
1898
     * @param bool $needPhoneNumber
1899
     * @param bool $needEmail
1900
     * @param bool $needShippingAddress
1901
     * @param int|null $replyToMessageId
1902
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
1903
     * @param bool $disableNotification
1904
     * @param string|null $providerData
1905
     * @param bool $sendPhoneNumberToProvider
1906
     * @param bool $sendEmailToProvider
1907
     * @param int|null $messageThreadId
1908
     * @param bool|null $protectContent
1909
     * @param bool|null $allowSendingWithoutReply
1910
     *
1911
     * @return Message
1912
     * @throws Exception
1913
     */
1914
    public function sendInvoice(
1915
        $chatId,
1916
        $title,
1917
        $description,
1918
        $payload,
1919
        $providerToken,
1920
        $startParameter,
1921
        $currency,
1922
        $prices,
1923
        $isFlexible = false,
1924
        $photoUrl = null,
1925
        $photoSize = null,
1926
        $photoWidth = null,
1927
        $photoHeight = null,
1928
        $needName = false,
1929
        $needPhoneNumber = false,
1930
        $needEmail = false,
1931
        $needShippingAddress = false,
1932
        $replyToMessageId = null,
1933
        $replyMarkup = null,
1934
        $disableNotification = false,
1935
        $providerData = null,
1936
        $sendPhoneNumberToProvider = false,
1937
        $sendEmailToProvider = false,
1938
        $messageThreadId = null,
1939
        $protectContent = null,
1940
        $allowSendingWithoutReply = null
1941
    ) {
1942
        return Message::fromResponse($this->call('sendInvoice', [
1943
            'chat_id' => $chatId,
1944
            'title' => $title,
1945
            'description' => $description,
1946
            'payload' => $payload,
1947
            'provider_token' => $providerToken,
1948
            'start_parameter' => $startParameter,
1949
            'currency' => $currency,
1950
            'prices' => json_encode($prices),
1951
            'is_flexible' => $isFlexible,
1952
            'photo_url' => $photoUrl,
1953
            'photo_size' => $photoSize,
1954
            'photo_width' => $photoWidth,
1955
            'photo_height' => $photoHeight,
1956
            'need_name' => $needName,
1957
            'need_phone_number' => $needPhoneNumber,
1958
            'need_email' => $needEmail,
1959
            'need_shipping_address' => $needShippingAddress,
1960
            'message_thread_id' => $messageThreadId,
1961
            'reply_to_message_id' => $replyToMessageId,
1962
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1963
            'disable_notification' => (bool) $disableNotification,
1964
            'provider_data' => $providerData,
1965
            'send_phone_number_to_provider' => (bool) $sendPhoneNumberToProvider,
1966
            'send_email_to_provider' => (bool) $sendEmailToProvider,
1967
            'protect_content' => (bool) $protectContent,
1968
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1969
        ]));
1970
    }
1971
1972
    /**
1973
     * If you sent an invoice requesting a shipping address and the parameter is_flexible was specified, the Bot API
1974
     * will send an Update with a shipping_query field to the bot. Use this method to reply to shipping queries.
1975
     * On success, True is returned.
1976
     *
1977
     * @param string $shippingQueryId
1978
     * @param bool $ok
1979
     * @param array $shippingOptions
1980
     * @param null|string $errorMessage
1981
     *
1982
     * @return bool
1983
     * @throws Exception
1984
     */
1985
    public function answerShippingQuery($shippingQueryId, $ok = true, $shippingOptions = [], $errorMessage = null)
1986
    {
1987
        return $this->call('answerShippingQuery', [
1988
            'shipping_query_id' => $shippingQueryId,
1989
            'ok' => (bool) $ok,
1990
            'shipping_options' => json_encode($shippingOptions),
1991
            'error_message' => $errorMessage
1992
        ]);
1993
    }
1994
1995
    /**
1996
     * Use this method to respond to such pre-checkout queries. On success, True is returned.
1997
     * Note: The Bot API must receive an answer within 10 seconds after the pre-checkout query was sent.
1998
     *
1999
     * @param string $preCheckoutQueryId
2000
     * @param bool $ok
2001
     * @param null|string $errorMessage
2002
     *
2003
     * @return bool
2004
     * @throws Exception
2005
     */
2006
    public function answerPreCheckoutQuery($preCheckoutQueryId, $ok = true, $errorMessage = null)
2007
    {
2008
        return $this->call('answerPreCheckoutQuery', [
2009
            'pre_checkout_query_id' => $preCheckoutQueryId,
2010
            'ok' => (bool) $ok,
2011
            'error_message' => $errorMessage
2012
        ]);
2013
    }
2014
2015
    /**
2016
     * Use this method to restrict a user in a supergroup.
2017
     * The bot must be an administrator in the supergroup for this to work and must have the appropriate admin rights.
2018
     * Pass True for all boolean parameters to lift restrictions from a user.
2019
     *
2020
     * @param string|int $chatId Unique identifier for the target chat or username of the target supergroup
2021
     *                           (in the format @supergroupusername)
2022
     * @param int $userId Unique identifier of the target user
2023
     * @param null|integer $untilDate Date when restrictions will be lifted for the user, unix time.
2024
     *                                If user is restricted for more than 366 days or less than 30 seconds from the current time,
2025
     *                                they are considered to be restricted forever
2026
     * @param bool $canSendMessages Pass True, if the user can send text messages, contacts, locations and venues
2027
     * @param bool $canSendMediaMessages No Pass True, if the user can send audios, documents, photos, videos,
2028
     *                                   video notes and voice notes, implies can_send_messages
2029
     * @param bool $canSendOtherMessages Pass True, if the user can send animations, games, stickers and
2030
     *                                   use inline bots, implies can_send_media_messages
2031
     * @param bool $canAddWebPagePreviews Pass True, if the user may add web page previews to their messages,
2032
     *                                    implies can_send_media_messages
2033
     *
2034
     * @return bool
2035
     * @throws Exception
2036
     */
2037
    public function restrictChatMember(
2038
        $chatId,
2039
        $userId,
2040
        $untilDate = null,
2041
        $canSendMessages = false,
2042
        $canSendMediaMessages = false,
2043
        $canSendOtherMessages = false,
2044
        $canAddWebPagePreviews = false
2045
    ) {
2046
        return $this->call('restrictChatMember', [
2047
            'chat_id' => $chatId,
2048
            'user_id' => $userId,
2049
            'until_date' => $untilDate,
2050
            'can_send_messages' => $canSendMessages,
2051
            'can_send_media_messages' => $canSendMediaMessages,
2052
            'can_send_other_messages' => $canSendOtherMessages,
2053
            'can_add_web_page_previews' => $canAddWebPagePreviews
2054
        ]);
2055
    }
2056
2057
    /**
2058
     * Use this method to promote or demote a user in a supergroup or a channel.
2059
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2060
     * Pass False for all boolean parameters to demote a user.
2061
     *
2062
     * @param string|int $chatId Unique identifier for the target chat or username of the target supergroup
2063
     *                           (in the format @supergroupusername)
2064
     * @param int $userId Unique identifier of the target user
2065
     * @param bool $canChangeInfo Pass True, if the administrator can change chat title, photo and other settings
2066
     * @param bool $canPostMessages Pass True, if the administrator can create channel posts, channels only
2067
     * @param bool $canEditMessages Pass True, if the administrator can edit messages of other users, channels only
2068
     * @param bool $canDeleteMessages Pass True, if the administrator can delete messages of other users
2069
     * @param bool $canInviteUsers Pass True, if the administrator can invite new users to the chat
2070
     * @param bool $canRestrictMembers Pass True, if the administrator can restrict, ban or unban chat members
2071
     * @param bool $canPinMessages Pass True, if the administrator can pin messages, supergroups only
2072
     * @param bool $canPromoteMembers Pass True, if the administrator can add new administrators with a subset of his
2073
     *                                own privileges or demote administrators that he has promoted,directly or
2074
     *                                indirectly (promoted by administrators that were appointed by him)
2075
     * @param bool $canManageTopics Pass True if the user is allowed to create, rename, close, and reopen forum topics, supergroups only
2076
     * @param bool $isAnonymous Pass True if the administrator's presence in the chat is hidden
2077
     * @return bool
2078
     *
2079
     * @throws Exception
2080
     * @throws HttpException
2081
     * @throws InvalidJsonException
2082
     */
2083
    public function promoteChatMember(
2084
        $chatId,
2085
        $userId,
2086
        $canChangeInfo = true,
2087
        $canPostMessages = true,
2088
        $canEditMessages = true,
2089
        $canDeleteMessages = true,
2090
        $canInviteUsers = true,
2091
        $canRestrictMembers = true,
2092
        $canPinMessages = true,
2093
        $canPromoteMembers = true,
2094
        $canManageTopics = true,
2095
        $isAnonymous = false
2096
    ) {
2097
        return $this->call('promoteChatMember', [
2098
            'chat_id' => $chatId,
2099
            'user_id' => $userId,
2100
            'is_anonymous' => $isAnonymous,
2101
            'can_change_info' => $canChangeInfo,
2102
            'can_post_messages' => $canPostMessages,
2103
            'can_edit_messages' => $canEditMessages,
2104
            'can_delete_messages' => $canDeleteMessages,
2105
            'can_invite_users' => $canInviteUsers,
2106
            'can_restrict_members' => $canRestrictMembers,
2107
            'can_pin_messages' => $canPinMessages,
2108
            'can_promote_members' => $canPromoteMembers,
2109
            'can_manage_topics' => $canManageTopics
2110
        ]);
2111
    }
2112
2113
    /**
2114
     * Use this method to export an invite link to a supergroup or a channel.
2115
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2116
     *
2117
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2118
     *                           (in the format @channelusername)
2119
     * @return string
2120
     * @throws Exception
2121
     */
2122
    public function exportChatInviteLink($chatId)
2123
    {
2124
        return $this->call('exportChatInviteLink', [
2125
            'chat_id' => $chatId
2126
        ]);
2127
    }
2128
2129
    /**
2130
     * Use this method to set a new profile photo for the chat. Photos can't be changed for private chats.
2131
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2132
     *
2133
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2134
     *                           (in the format @channelusername)
2135
     * @param \CURLFile|string $photo New chat photo, uploaded using multipart/form-data
2136
     *
2137
     * @return bool
2138
     * @throws Exception
2139
     */
2140
    public function setChatPhoto($chatId, $photo)
2141
    {
2142
        return $this->call('setChatPhoto', [
2143
            'chat_id' => $chatId,
2144
            'photo' => $photo
2145
        ]);
2146
    }
2147
2148
    /**
2149
     * Use this method to delete a chat photo. Photos can't be changed for private chats.
2150
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2151
     *
2152
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2153
     *                           (in the format @channelusername)
2154
     *
2155
     * @return bool
2156
     * @throws Exception
2157
     */
2158
    public function deleteChatPhoto($chatId)
2159
    {
2160
        return $this->call('deleteChatPhoto', [
2161
            'chat_id' => $chatId
2162
        ]);
2163
    }
2164
2165
    /**
2166
     * Use this method to change the title of a chat. Titles can't be changed for private chats.
2167
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2168
     *
2169
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2170
     *                           (in the format @channelusername)
2171
     * @param string $title New chat title, 1-255 characters
2172
     *
2173
     * @return bool
2174
     * @throws Exception
2175
     */
2176
    public function setChatTitle($chatId, $title)
2177
    {
2178
        return $this->call('setChatTitle', [
2179
            'chat_id' => $chatId,
2180
            'title' => $title
2181
        ]);
2182
    }
2183
2184
    /**
2185
     * Use this method to change the description of a supergroup or a channel.
2186
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2187
     *
2188
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2189
     *                           (in the format @channelusername)
2190
     * @param string|null $description New chat description, 0-255 characters
2191
     *
2192
     * @return bool
2193
     * @throws Exception
2194
     */
2195
    public function setChatDescription($chatId, $description = null)
2196
    {
2197
        return $this->call('setChatDescription', [
2198
            'chat_id' => $chatId,
2199
            'title' => $description
2200
        ]);
2201
    }
2202
2203
    /**
2204
     * Use this method to pin a message in a supergroup.
2205
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2206
     *
2207
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2208
     *                           (in the format @channelusername)
2209
     * @param int $messageId Identifier of a message to pin
2210
     * @param bool $disableNotification
2211
     *
2212
     * @return bool
2213
     * @throws Exception
2214
     */
2215
    public function pinChatMessage($chatId, $messageId, $disableNotification = false)
2216
    {
2217
        return $this->call('pinChatMessage', [
2218
            'chat_id' => $chatId,
2219
            'message_id' => $messageId,
2220
            'disable_notification' => $disableNotification
2221
        ]);
2222
    }
2223
2224
    /**
2225
     * Use this method to unpin a message in a supergroup chat.
2226
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2227
     *
2228
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2229
     *                           (in the format @channelusername)
2230
     *
2231
     * @return bool
2232
     * @throws Exception
2233
     */
2234
    public function unpinChatMessage($chatId)
2235
    {
2236
        return $this->call('unpinChatMessage', [
2237
            'chat_id' => $chatId
2238
        ]);
2239
    }
2240
2241
    /**
2242
     * Use this method to get up to date information about the chat
2243
     * (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.).
2244
     *
2245
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2246
     *                           (in the format @channelusername)
2247
     *
2248
     * @return Chat
2249
     * @throws Exception
2250
     */
2251
    public function getChat($chatId)
2252
    {
2253
        return Chat::fromResponse($this->call('getChat', [
2254
            'chat_id' => $chatId
2255
        ]));
2256
    }
2257
2258
    /**
2259
     * Use this method to get information about a member of a chat.
2260
     *
2261
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2262
     *                           (in the format @channelusername)
2263
     * @param int $userId
2264
     *
2265
     * @return ChatMember
2266
     * @throws Exception
2267
     */
2268
    public function getChatMember($chatId, $userId)
2269
    {
2270
        return ChatMember::fromResponse($this->call('getChatMember', [
2271
            'chat_id' => $chatId,
2272
            'user_id' => $userId
2273
        ]));
2274
    }
2275
2276
    /**
2277
     * Use this method for your bot to leave a group, supergroup or channel.
2278
     *
2279
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2280
     *                           (in the format @channelusername)
2281
     *
2282
     * @return bool
2283
     * @throws Exception
2284
     */
2285
    public function leaveChat($chatId)
2286
    {
2287
        return $this->call('leaveChat', [
2288
            'chat_id' => $chatId
2289
        ]);
2290
    }
2291
2292
    /**
2293
     * Use this method to get the number of members in a chat.
2294
     *
2295
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2296
     *                           (in the format @channelusername)
2297
     *
2298
     * @return int
2299
     * @throws Exception
2300
     */
2301
    public function getChatMembersCount($chatId)
2302
    {
2303
        @trigger_error(sprintf('Method "%s::%s" is deprecated. Use "getChatMemberCount"', __CLASS__, __METHOD__), \E_USER_DEPRECATED);
2304
2305
        return $this->call('getChatMembersCount', [
2306
            'chat_id' => $chatId
2307
        ]);
2308
    }
2309
2310
    /**
2311
     * Use this method to get the number of members in a chat. Returns Int on success.
2312
     *
2313
     * @param string|int $chatId Unique identifier for the target chat or username of the target supergroup or channel
2314
     *                           (in the format @channelusername)
2315
     *
2316
     * @return int
2317
     * @throws Exception
2318
     */
2319
    public function getChatMemberCount($chatId)
2320
    {
2321
        return $this->call('getChatMemberCount', [
2322
            'chat_id' => $chatId
2323
        ]);
2324
    }
2325
2326
    /**
2327
     * Use this method to get a list of administrators in a chat.
2328
     *
2329
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2330
     *                           (in the format @channelusername)
2331
     *
2332
     * @return ChatMember[]
2333
     * @throws InvalidArgumentException
2334
     * @throws Exception
2335
     */
2336
    public function getChatAdministrators($chatId)
2337
    {
2338
        return ArrayOfChatMemberEntity::fromResponse(
2339
            $this->call(
2340
                'getChatAdministrators',
2341
                [
2342
                    'chat_id' => $chatId
2343
                ]
2344
            )
2345
        );
2346
    }
2347
2348
    /**
2349
     * As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1 minute long.
2350
     * Use this method to send video messages.
2351
     * On success, the sent Message is returned.
2352
     *
2353
     * @param int|string $chatId chat_id or @channel_name
2354
     * @param \CURLFile|string $videoNote
2355
     * @param int|null $duration
2356
     * @param int|null $length
2357
     * @param int|null $replyToMessageId
2358
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
2359
     * @param bool $disableNotification
2360
     * @param int|null $messageThreadId
2361
     * @param bool|null $protectContent
2362
     * @param bool|null $allowSendingWithoutReply
2363
     * @param \CURLFile|\CURLStringFile|string|null $thumbnail
2364
     *
2365
     * @return Message
2366
     * @throws InvalidArgumentException
2367
     * @throws Exception
2368
     */
2369
    public function sendVideoNote(
2370
        $chatId,
2371
        $videoNote,
2372
        $duration = null,
2373
        $length = null,
2374
        $replyToMessageId = null,
2375
        $replyMarkup = null,
2376
        $disableNotification = false,
2377
        $messageThreadId = null,
2378
        $protectContent = null,
2379
        $allowSendingWithoutReply = null,
2380
        $thumbnail = null
2381
    ) {
2382
        return Message::fromResponse($this->call('sendVideoNote', [
2383
            'chat_id' => $chatId,
2384
            'video_note' => $videoNote,
2385
            'duration' => $duration,
2386
            'length' => $length,
2387
            'message_thread_id' => $messageThreadId,
2388
            'reply_to_message_id' => $replyToMessageId,
2389
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
2390
            'disable_notification' => (bool) $disableNotification,
2391
            'protect_content' => (bool) $protectContent,
2392
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
2393
            'thumbnail' => $thumbnail,
2394
        ]));
2395
    }
2396
2397
    /**
2398
     * Use this method to send a group of photos or videos as an album.
2399
     * On success, the sent \TelegramBot\Api\Types\Message is returned.
2400
     *
2401
     * @param int|string $chatId
2402
     * @param ArrayOfInputMedia $media
2403
     * @param bool $disableNotification
2404
     * @param int|null $replyToMessageId
2405
     * @param int|null $messageThreadId
2406
     * @param bool|null $protectContent
2407
     * @param bool|null $allowSendingWithoutReply
2408
     * @param array<string, \CURLFile|\CURLStringFile> $attachments Attachments to use in attach://<attachment>
2409
     *
2410
     * @return Message[]
2411
     * @throws Exception
2412
     */
2413
    public function sendMediaGroup(
2414
        $chatId,
2415
        $media,
2416
        $disableNotification = false,
2417
        $replyToMessageId = null,
2418
        $messageThreadId = null,
2419
        $protectContent = null,
2420
        $allowSendingWithoutReply = null,
2421
        $attachments = []
2422
    ) {
2423
        return ArrayOfMessages::fromResponse($this->call('sendMediaGroup', [
2424
            'chat_id' => $chatId,
2425
            'media' => $media->toJson(),
2426
            'message_thread_id' => $messageThreadId,
2427
            'reply_to_message_id' => (int) $replyToMessageId,
2428
            'disable_notification' => (bool) $disableNotification,
2429
            'protect_content' => (bool) $protectContent,
2430
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
2431
        ] + $attachments));
2432
    }
2433
2434
    /**
2435
     * Enable proxy for curl requests. Empty string will disable proxy.
2436
     *
2437
     * @param string $proxyString
2438
     * @param bool $socks5
2439
     *
2440
     * @return BotApi
2441
     */
2442
    public function setProxy($proxyString = '', $socks5 = false)
2443
    {
2444
        if (empty($proxyString)) {
2445
            $this->proxySettings = [];
2446
            return $this;
2447
        }
2448
2449
        $this->proxySettings = [
2450
            CURLOPT_PROXY => $proxyString,
2451
            CURLOPT_HTTPPROXYTUNNEL => true,
2452
        ];
2453
2454
        if ($socks5) {
2455
            $this->proxySettings[CURLOPT_PROXYTYPE] = CURLPROXY_SOCKS5;
2456
        }
2457
        return $this;
2458
    }
2459
2460
    /**
2461
     * Use this method to send a native poll. A native poll can't be sent to a private chat.
2462
     * On success, the sent \TelegramBot\Api\Types\Message is returned.
2463
     *
2464
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2465
     *                           (in the format @channelusername)
2466
     * @param string $question Poll question, 1-255 characters
2467
     * @param array $options A JSON-serialized list of answer options, 2-10 strings 1-100 characters each
2468
     * @param bool $isAnonymous True, if the poll needs to be anonymous, defaults to True
2469
     * @param string|null $type Poll type, “quiz” or “regular”, defaults to “regular”
2470
     * @param bool $allowsMultipleAnswers True, if the poll allows multiple answers,
2471
     *                                    ignored for polls in quiz mode, defaults to False
2472
     * @param string|null $correctOptionId 0-based identifier of the correct answer option, required for polls in quiz mode
2473
     * @param bool $isClosed Pass True, if the poll needs to be immediately closed. This can be useful for poll preview.
2474
     * @param bool $disableNotification Sends the message silently. Users will receive a notification with no sound.
2475
     * @param int|null $replyToMessageId If the message is a reply, ID of the original message
2476
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup Additional interface options. A JSON-serialized object for an inline keyboard,
2477
     *                                                                                                  custom reply keyboard, instructions to remove reply
2478
     *                                                                                                  keyboard or to force a reply from the user.
2479
     * @param int|null $messageThreadId Unique identifier for the target message thread (topic) of the forum; for forum supergroups only
2480
     * @param bool|null $protectContent
2481
     * @param bool|null $allowSendingWithoutReply
2482
     *
2483
     * @return Message
2484
     * @throws Exception
2485
     * @throws HttpException
2486
     * @throws InvalidJsonException
2487
     */
2488
    public function sendPoll(
2489
        $chatId,
2490
        $question,
2491
        $options,
2492
        $isAnonymous = false,
2493
        $type = null,
2494
        $allowsMultipleAnswers = false,
2495
        $correctOptionId = null,
2496
        $isClosed = false,
2497
        $disableNotification = false,
2498
        $replyToMessageId = null,
2499
        $replyMarkup = null,
2500
        $messageThreadId = null,
2501
        $protectContent = null,
2502
        $allowSendingWithoutReply = null
2503
    ) {
2504
        return Message::fromResponse($this->call('sendPoll', [
2505
            'chat_id' => $chatId,
2506
            'question' => $question,
2507
            'options' => json_encode($options),
2508
            'is_anonymous' => (bool) $isAnonymous,
2509
            'type' => (string) $type,
2510
            'allows_multiple_answers' => (bool) $allowsMultipleAnswers,
2511
            'correct_option_id' => (int) $correctOptionId,
2512
            'is_closed' => (bool) $isClosed,
2513
            'disable_notification' => (bool) $disableNotification,
2514
            'message_thread_id' => $messageThreadId,
2515
            'reply_to_message_id' => (int) $replyToMessageId,
2516
            'reply_markup' => $replyMarkup === null ? $replyMarkup : $replyMarkup->toJson(),
2517
            'protect_content' => (bool) $protectContent,
2518
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
2519
        ]));
2520
    }
2521
2522
    /**
2523
     * Use this method to send a dice, which will have a random value from 1 to 6.
2524
     * On success, the sent Message is returned. (Yes, we're aware of the “proper” singular of die.
2525
     * But it's awkward, and we decided to help it change. One dice at a time!)
2526
     *
2527
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2528
     *                           (in the format @channelusername)
2529
     * @param string $emoji Emoji on which the dice throw animation is based. Currently, must be one of “🎲”,
2530
     *                      “🎯”, “🏀”, “⚽”, or “🎰”. Dice can have values 1-6 for “🎲” and “🎯”, values 1-5 for “🏀” and “⚽”, and
2531
     *                      values 1-64 for “🎰”. Defaults to “🎲
2532
     * @param bool $disableNotification Sends the message silently. Users will receive a notification with no sound.
2533
     * @param string|null $replyToMessageId If the message is a reply, ID of the original message
2534
     * @param bool $allowSendingWithoutReply Pass True, if the message should be sent even if the specified replied-to
2535
     *                                       message is not found,
2536
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup Additional interface options. A JSON-serialized object for an inline keyboard,
2537
     *                                                                                                  custom reply keyboard, instructions to remove reply
2538
     *                                                                                                  keyboard or to force a reply from the user.
2539
     * @param int|null $messageThreadId
2540
     * @param bool|null $protectContent
2541
     *
2542
     * @return Message
2543
     * @throws Exception
2544
     * @throws HttpException
2545
     * @throws InvalidJsonException
2546
     */
2547
    public function sendDice(
2548
        $chatId,
2549
        $emoji,
2550
        $disableNotification = false,
2551
        $replyToMessageId = null,
2552
        $allowSendingWithoutReply = false,
2553
        $replyMarkup = null,
2554
        $messageThreadId = null,
2555
        $protectContent = null
2556
    ) {
2557
        return Message::fromResponse($this->call('sendDice', [
2558
            'chat_id' => $chatId,
2559
            'emoji' => $emoji,
2560
            'disable_notification' => (bool) $disableNotification,
2561
            'message_thread_id' => $messageThreadId,
2562
            'reply_to_message_id' => (int) $replyToMessageId,
2563
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
2564
            'reply_markup' => $replyMarkup === null ? $replyMarkup : $replyMarkup->toJson(),
2565
            'protect_content' => (bool) $protectContent,
2566
        ]));
2567
    }
2568
2569
    /**
2570
     * Use this method to stop a poll which was sent by the bot.
2571
     * On success, the stopped \TelegramBot\Api\Types\Poll with the final results is returned.
2572
     *
2573
     * @param int|string $chatId
2574
     * @param int $messageId
2575
     * @param InlineKeyboardMarkup|null $replyMarkup
2576
     * @return Poll
2577
     * @throws InvalidArgumentException
2578
     * @throws Exception
2579
     */
2580
    public function stopPoll(
2581
        $chatId,
2582
        $messageId,
2583
        $replyMarkup = null
2584
    ) {
2585
        return Poll::fromResponse($this->call('stopPoll', [
2586
            'chat_id' => $chatId,
2587
            'message_id' => $messageId,
2588
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
2589
        ]));
2590
    }
2591
2592
    /**
2593
     * Use this method to create a topic in a forum supergroup chat.
2594
     * The bot must be an administrator in the chat for this to work
2595
     * and must have the can_manage_topics administrator rights.
2596
     * Returns information about the created topic as a ForumTopic object.
2597
     *
2598
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2599
     * @param string $name Topic name, 1-128 characters
2600
     * @param int $iconColor Color of the topic icon in RGB format.
2601
     *                       Currently, must be one of 7322096 (0x6FB9F0), 16766590 (0xFFD67E), 13338331 (0xCB86DB),
2602
     *                       9367192 (0x8EEE98), 16749490 (0xFF93B2), or 16478047 (0xFB6F5F)
2603
     * @param int|null $iconCustomEmojiId Unique identifier of the custom emoji shown as the topic icon.
2604
     *                                    Use getForumTopicIconStickers to get all allowed custom emoji identifiers.
2605
     *
2606
     * @return ForumTopic
2607
     *
2608
     * @throws Exception
2609
     *
2610
     * @author bernard-ng <[email protected]>
2611
     */
2612
    public function createForumTopic(
2613
        $chatId,
2614
        $name,
2615
        $iconColor,
2616
        $iconCustomEmojiId = null
2617
    ) {
2618
        return ForumTopic::fromResponse($this->call('createForumTopic', [
2619
            'chat_id' => $chatId,
2620
            'name' => $name,
2621
            'icon_color' => $iconColor,
2622
            'icon_custom_emoji_id' => $iconCustomEmojiId,
2623
        ]));
2624
    }
2625
2626
    /**
2627
     * Use this method to edit name and icon of a topic in a forum supergroup chat.
2628
     * The bot must be an administrator in the chat for this to work and must have can_manage_topics administrator rights,
2629
     * unless it is the creator of the topic. Returns True on success.
2630
     *
2631
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2632
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2633
     * @param string $name Topic name, 1-128 characters
2634
     * @param int|null $iconCustomEmojiId Unique identifier of the custom emoji shown as the topic icon.
2635
     *                                    Use getForumTopicIconStickers to get all allowed custom emoji identifiers.
2636
     *
2637
     * @return bool
2638
     * @throws Exception
2639
     *
2640
     * @author bernard-ng <[email protected]>
2641
     */
2642
    public function editForumTopic(
2643
        $chatId,
2644
        $messageThreadId,
2645
        $name,
2646
        $iconCustomEmojiId = null
2647
    ) {
2648
        return $this->call('editForumTopic', [
2649
            'chat_id' => $chatId,
2650
            'message_thread_id' => $messageThreadId,
2651
            'name' => $name,
2652
            'icon_custom_emoji_id' => $iconCustomEmojiId,
2653
        ]);
2654
    }
2655
2656
    /**
2657
     * Use this method to delete a topic in a forum supergroup chat.
2658
     * The bot must be an administrator in the chat for this to work and must have can_manage_topics administrator rights,
2659
     * unless it is the creator of the topic. Returns True on success.
2660
     *
2661
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2662
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2663
     *
2664
     * @return bool
2665
     * @throws Exception
2666
     *
2667
     * @author bernard-ng <[email protected]>
2668
     */
2669
    public function closeForumTopic($chatId, $messageThreadId)
2670
    {
2671
        return $this->call('closeForumTopic', [
2672
            'chat_id' => $chatId,
2673
            'message_thread_id' => $messageThreadId,
2674
        ]);
2675
    }
2676
2677
    /**
2678
     * Use this method to reopen a closed topic in a forum supergroup chat.
2679
     * The bot must be an administrator in the chat for this to work and must have the can_manage_topics administrator rights,
2680
     * unless it is the creator of the topic. Returns True on success.
2681
     *
2682
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2683
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2684
     *
2685
     * @return bool
2686
     * @throws Exception
2687
     *
2688
     * @author bernard-ng <[email protected]>
2689
     */
2690
    public function reopenForumTopic($chatId, $messageThreadId)
2691
    {
2692
        return $this->call('reopenForumTopic', [
2693
            'chat_id' => $chatId,
2694
            'message_thread_id' => $messageThreadId,
2695
        ]);
2696
    }
2697
2698
    /**
2699
     * Use this method to delete a forum topic along with all its messages in a forum supergroup chat.
2700
     * The bot must be an administrator in the chat for this to work and must have the can_delete_messages administrator rights.
2701
     * Returns True on success.
2702
     *
2703
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2704
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2705
     *
2706
     * @return bool
2707
     * @throws Exception
2708
     *
2709
     * @author bernard-ng <[email protected]>
2710
     */
2711
    public function deleteForumTopic($chatId, $messageThreadId)
2712
    {
2713
        return $this->call('deleteForumTopic', [
2714
            'chat_id' => $chatId,
2715
            'message_thread_id' => $messageThreadId,
2716
        ]);
2717
    }
2718
2719
    /**
2720
     * Use this method to clear the list of pinned messages in a forum topic.
2721
     * 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.
2722
     * Returns True on success.
2723
     *
2724
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2725
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2726
     *
2727
     * @return bool
2728
     * @throws Exception
2729
     *
2730
     * @author bernard-ng <[email protected]>
2731
     */
2732
    public function unpinAllForumTopicMessages($chatId, $messageThreadId)
2733
    {
2734
        return $this->call('unpinAllForumTopicMessages', [
2735
            'chat_id' => $chatId,
2736
            'message_thread_id' => $messageThreadId,
2737
        ]);
2738
    }
2739
2740
    /**
2741
     * Use this method to get custom emoji stickers, which can be used as a forum topic icon by any user.
2742
     * Requires no parameters. Returns an Array of Sticker objects.
2743
     *
2744
     * @return Sticker[]
2745
     * @throws Exception
2746
     *
2747
     * @author bernard-ng <[email protected]>
2748
     */
2749
    public function getForumTopicIconStickers()
2750
    {
2751
        return ArrayOfSticker::fromResponse($this->call('getForumTopicIconStickers'));
2752
    }
2753
2754
    /**
2755
     * @param string $webAppQueryId
2756
     * @param AbstractInlineQueryResult $result
2757
     * @return SentWebAppMessage
2758
     * @throws Exception
2759
     * @throws HttpException
2760
     * @throws InvalidArgumentException
2761
     * @throws InvalidJsonException
2762
     */
2763
    public function answerWebAppQuery($webAppQueryId, $result)
2764
    {
2765
        return SentWebAppMessage::fromResponse($this->call('answerWebAppQuery', [
2766
            'web_app_query_id' => $webAppQueryId,
2767
            'result' => $result->toJson(),
2768
        ]));
2769
    }
2770
2771
    /**
2772
     * Set an option for a cURL transfer
2773
     *
2774
     * @param int $option The CURLOPT_XXX option to set
2775
     * @param mixed $value The value to be set on option
2776
     *
2777
     * @return void
2778
     */
2779
    public function setCurlOption($option, $value)
2780
    {
2781
        $this->customCurlOptions[$option] = $value;
2782
    }
2783
2784
    /**
2785
     * Unset an option for a cURL transfer
2786
     *
2787
     * @param int $option The CURLOPT_XXX option to unset
2788
     *
2789
     * @return void
2790
     */
2791
    public function unsetCurlOption($option)
2792
    {
2793
        unset($this->customCurlOptions[$option]);
2794
    }
2795
2796
    /**
2797
     * Clean custom options
2798
     *
2799
     * @return void
2800
     */
2801
    public function resetCurlOptions()
2802
    {
2803
        $this->customCurlOptions = [];
2804
    }
2805
}
2806