Passed
Pull Request — master (#433)
by Alexander
02:29
created

BotApi::setStickerSetThumbnail()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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

201
            $this->tracker = /** @scrutinizer ignore-deprecated */ new Botan($trackerToken);
Loading history...
202
        }
203
    }
204
205
    /**
206
     * Set return array
207
     *
208
     * @param bool $mode
209
     *
210
     * @return $this
211
     */
212
    public function setModeObject($mode = true)
213
    {
214
        $this->returnArray = !$mode;
215
216
        return $this;
217
    }
218
219
    /**
220
     * Call method
221
     *
222
     * @param string $method
223
     * @param array|null $data
224
     * @param int $timeout
225
     *
226
     * @return mixed
227
     * @throws Exception
228
     * @throws HttpException
229
     * @throws InvalidJsonException
230
     */
231
    public function call($method, array $data = null, $timeout = 10)
232
    {
233
        $options = $this->proxySettings + [
234
            CURLOPT_URL => $this->getUrl().'/'.$method,
235
            CURLOPT_RETURNTRANSFER => true,
236
            CURLOPT_POST => null,
237
            CURLOPT_POSTFIELDS => null,
238
            CURLOPT_TIMEOUT => $timeout,
239
        ];
240
241
        if ($data) {
242
            $options[CURLOPT_POST] = true;
243
            $options[CURLOPT_POSTFIELDS] = $data;
244
        }
245
246
        if (!empty($this->customCurlOptions)) {
247
            $options = $this->customCurlOptions + $options;
248
        }
249
250
        $response = self::jsonValidate($this->executeCurl($options), $this->returnArray);
251
252
        if (\is_array($response)) {
253
            if (!isset($response['ok']) || !$response['ok']) {
254
                throw new Exception($response['description'], $response['error_code']);
255
            }
256
257
            return $response['result'];
258
        }
259
260
        if (!$response->ok) {
261
            throw new Exception($response->description, $response->error_code);
262
        }
263
264
        return $response->result;
265
    }
266
267
    /**
268
     * curl_exec wrapper for response validation
269
     *
270
     * @param array $options
271
     *
272
     * @return string
273
     *
274
     * @throws HttpException
275
     */
276
    protected function executeCurl(array $options)
277
    {
278
        curl_setopt_array($this->curl, $options);
279
280
        /** @var string|false $result */
281
        $result = curl_exec($this->curl);
282
        self::curlValidate($this->curl, $result);
283
        if ($result === false) {
0 ignored issues
show
introduced by
The condition $result === false is always false.
Loading history...
284
            throw new HttpException(curl_error($this->curl), curl_errno($this->curl));
285
        }
286
287
        return $result;
288
    }
289
290
    /**
291
     * Response validation
292
     *
293
     * @param resource $curl
294
     * @param string|false|null $response
295
     *
296
     * @throws HttpException
297
     *
298
     * @return void
299
     */
300
    public static function curlValidate($curl, $response = null)
301
    {
302
        if ($response) {
303
            $json = json_decode($response, true) ?: [];
304
        } else {
305
            $json = [];
306
        }
307
        if (($httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE))
308
            && !in_array($httpCode, [self::DEFAULT_STATUS_CODE, self::NOT_MODIFIED_STATUS_CODE])
309
        ) {
310
            $errorDescription = array_key_exists('description', $json) ? $json['description'] : self::$codes[$httpCode];
311
            $errorParameters = array_key_exists('parameters', $json) ? $json['parameters'] : [];
312
            throw new HttpException($errorDescription, $httpCode, null, $errorParameters);
313
        }
314
    }
315
316
    /**
317
     * JSON validation
318
     *
319
     * @param string $jsonString
320
     * @param bool $asArray
321
     *
322
     * @return object|array
323
     * @throws InvalidJsonException
324
     */
325
    public static function jsonValidate($jsonString, $asArray)
326
    {
327
        $json = json_decode($jsonString, $asArray);
328
329
        if (json_last_error() != JSON_ERROR_NONE) {
330
            throw new InvalidJsonException(json_last_error_msg(), json_last_error());
331
        }
332
333
        return $json;
334
    }
335
336
    /**
337
     * Use this method to send text messages. On success, the sent \TelegramBot\Api\Types\Message is returned.
338
     *
339
     * @param int|float|string $chatId
340
     * @param string $text
341
     * @param string|null $parseMode
342
     * @param bool $disablePreview
343
     * @param int|null $replyToMessageId
344
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardHide|ReplyKeyboardRemove|ForceReply|null $replyMarkup
345
     * @param bool $disableNotification
346
     * @param int|null $messageThreadId
347
     * @param bool|null $protectContent
348
     * @param bool|null $allowSendingWithoutReply
349
     *
350
     * @return Message
351
     * @throws InvalidArgumentException
352
     * @throws Exception
353
     */
354
    public function sendMessage(
355
        $chatId,
356
        $text,
357
        $parseMode = null,
358
        $disablePreview = false,
359
        $replyToMessageId = null,
360
        $replyMarkup = null,
361
        $disableNotification = false,
362
        $messageThreadId = null,
363
        $protectContent = null,
364
        $allowSendingWithoutReply = null
365
    ) {
366
        return Message::fromResponse($this->call('sendMessage', [
367
            'chat_id' => $chatId,
368
            'text' => $text,
369
            'message_thread_id' => $messageThreadId,
370
            'parse_mode' => $parseMode,
371
            'disable_web_page_preview' => $disablePreview,
372
            'reply_to_message_id' => (int) $replyToMessageId,
373
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
374
            'disable_notification' => (bool) $disableNotification,
375
            'protect_content' => (bool) $protectContent,
376
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
377
        ]));
378
    }
379
380
    /**
381
     * @param int|string $chatId
382
     * @param int|string $fromChatId
383
     * @param int $messageId
384
     * @param string|null $caption
385
     * @param string|null $parseMode
386
     * @param ArrayOfMessageEntity|null $captionEntities
387
     * @param bool $disableNotification
388
     * @param int|null $replyToMessageId
389
     * @param bool $allowSendingWithoutReply
390
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
391
     * @param int|null $messageThreadId
392
     * @param bool|null $protectContent
393
     *
394
     * @return MessageId
395
     * @throws Exception
396
     * @throws HttpException
397
     * @throws InvalidJsonException
398
     */
399
    public function copyMessage(
400
        $chatId,
401
        $fromChatId,
402
        $messageId,
403
        $caption = null,
404
        $parseMode = null,
405
        $captionEntities = null,
406
        $disableNotification = false,
407
        $replyToMessageId = null,
408
        $allowSendingWithoutReply = false,
409
        $replyMarkup = null,
410
        $messageThreadId = null,
411
        $protectContent = null
412
    ) {
413
        return MessageId::fromResponse($this->call('copyMessage', [
414
            'chat_id' => $chatId,
415
            'from_chat_id' => $fromChatId,
416
            'message_id' => (int) $messageId,
417
            'caption' => $caption,
418
            'parse_mode' => $parseMode,
419
            'caption_entities' => $captionEntities,
420
            'disable_notification' => (bool) $disableNotification,
421
            'message_thread_id' => $messageThreadId,
422
            'reply_to_message_id' => (int) $replyToMessageId,
423
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
424
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
425
            'protect_content' => (bool) $protectContent,
426
        ]));
427
    }
428
429
    /**
430
     * Use this method to send phone contacts
431
     *
432
     * @param int|string $chatId chat_id or @channel_name
433
     * @param string $phoneNumber
434
     * @param string $firstName
435
     * @param string $lastName
436
     * @param int|null $replyToMessageId
437
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
438
     * @param bool $disableNotification
439
     * @param int|null $messageThreadId
440
     * @param bool|null $protectContent
441
     * @param bool|null $allowSendingWithoutReply
442
     *
443
     * @return Message
444
     * @throws Exception
445
     */
446
    public function sendContact(
447
        $chatId,
448
        $phoneNumber,
449
        $firstName,
450
        $lastName = null,
451
        $replyToMessageId = null,
452
        $replyMarkup = null,
453
        $disableNotification = false,
454
        $messageThreadId = null,
455
        $protectContent = null,
456
        $allowSendingWithoutReply = null
457
    ) {
458
        return Message::fromResponse($this->call('sendContact', [
459
            'chat_id' => $chatId,
460
            'phone_number' => $phoneNumber,
461
            'first_name' => $firstName,
462
            'last_name' => $lastName,
463
            'message_thread_id' => $messageThreadId,
464
            'reply_to_message_id' => $replyToMessageId,
465
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
466
            'disable_notification' => (bool) $disableNotification,
467
            'protect_content' => (bool) $protectContent,
468
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
469
        ]));
470
    }
471
472
    /**
473
     * Use this method when you need to tell the user that something is happening on the bot's side.
474
     * The status is set for 5 seconds or less (when a message arrives from your bot,
475
     * Telegram clients clear its typing status).
476
     *
477
     * We only recommend using this method when a response from the bot will take a noticeable amount of time to arrive.
478
     *
479
     * Type of action to broadcast. Choose one, depending on what the user is about to receive:
480
     * `typing` for text messages, `upload_photo` for photos, `record_video` or `upload_video` for videos,
481
     * `record_audio` or upload_audio for audio files, `upload_document` for general files,
482
     * `find_location` for location data.
483
     *
484
     * @param int $chatId
485
     * @param string $action
486
     *
487
     * @return bool
488
     * @throws Exception
489
     */
490
    public function sendChatAction($chatId, $action)
491
    {
492
        return $this->call('sendChatAction', [
493
            'chat_id' => $chatId,
494
            'action' => $action,
495
        ]);
496
    }
497
498
    /**
499
     * Use this method to get a list of profile pictures for a user.
500
     *
501
     * @param int $userId
502
     * @param int $offset
503
     * @param int $limit
504
     *
505
     * @return UserProfilePhotos
506
     * @throws Exception
507
     */
508
    public function getUserProfilePhotos($userId, $offset = 0, $limit = 100)
509
    {
510
        return UserProfilePhotos::fromResponse($this->call('getUserProfilePhotos', [
511
            'user_id' => (int) $userId,
512
            'offset' => (int) $offset,
513
            'limit' => (int) $limit,
514
        ]));
515
    }
516
517
    /**
518
     * Use this method to specify a url and receive incoming updates via an outgoing webhook.
519
     * Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url,
520
     * containing a JSON-serialized Update.
521
     * In case of an unsuccessful request, we will give up after a reasonable amount of attempts.
522
     *
523
     * @param string $url HTTPS url to send updates to. Use an empty string to remove webhook integration
524
     * @param \CURLFile|string $certificate Upload your public key certificate
525
     *                                      so that the root certificate in use can be checked
526
     * @param string|null $ipAddress The fixed IP address which will be used to send webhook requests
527
     *                               instead of the IP address resolved through DNS
528
     * @param int|null $maxConnections The maximum allowed number of simultaneous HTTPS connections to the webhook
529
     *                                 for update delivery, 1-100. Defaults to 40. Use lower values to limit
530
     *                                 the load on your bot's server, and higher values to increase your bot's throughput.
531
     * @param array|null $allowedUpdates A JSON-serialized list of the update types you want your bot to receive.
532
     *                                   For example, specify [“message”, “edited_channel_post”, “callback_query”]
533
     *                                   to only receive updates of these types. See Update for a complete list of available update types.
534
     *                                   Specify an empty list to receive all update types except chat_member (default).
535
     *                                   If not specified, the previous setting will be used.
536
     *                                   Please note that this parameter doesn't affect updates created before the call to the setWebhook,
537
     *                                   so unwanted updates may be received for a short period of time.
538
     * @param bool|null $dropPendingUpdates Pass True to drop all pending updates
539
     * @param string|null $secretToken A secret token to be sent in a header “X-Telegram-Bot-Api-Secret-Token” in every webhook request,
540
     *                                 1-256 characters. Only characters A-Z, a-z, 0-9, _ and - are allowed.
541
     *                                 The header is useful to ensure that the request comes from a webhook set by you.
542
     *
543
     * @return string
544
     *
545
     * @throws Exception
546
     */
547
    public function setWebhook(
548
        $url = '',
549
        $certificate = null,
550
        $ipAddress = null,
551
        $maxConnections = 40,
552
        $allowedUpdates = null,
553
        $dropPendingUpdates = false,
554
        $secretToken = null
555
    ) {
556
        return $this->call('setWebhook', [
557
            'url' => $url,
558
            'certificate' => $certificate,
559
            'ip_address' => $ipAddress,
560
            'max_connections' => $maxConnections,
561
            'allowed_updates' => $allowedUpdates,
562
            'drop_pending_updates' => $dropPendingUpdates,
563
            'secret_token' => $secretToken
564
        ]);
565
    }
566
567
    /**
568
     * Use this method to clear webhook and use getUpdates again!
569
     *
570
     * @param bool $dropPendingUpdates Pass True to drop all pending updates
571
     *
572
     * @return mixed
573
     *
574
     * @throws Exception
575
     */
576
    public function deleteWebhook($dropPendingUpdates = false)
577
    {
578
        return $this->call('deleteWebhook', ['drop_pending_updates' => $dropPendingUpdates]);
579
    }
580
581
    /**
582
     * Use this method to get current webhook status. Requires no parameters.
583
     * On success, returns a WebhookInfo object. If the bot is using getUpdates,
584
     * will return an object with the url field empty.
585
     *
586
     * @return WebhookInfo
587
     * @throws Exception
588
     * @throws InvalidArgumentException
589
     */
590
    public function getWebhookInfo()
591
    {
592
        return WebhookInfo::fromResponse($this->call('getWebhookInfo'));
593
    }
594
595 2
    /**
596
     * A simple method for testing your bot's auth token.Requires no parameters.
597 2
     * Returns basic information about the bot in form of a User object.
598 2
     *
599 2
     * @return User
600 2
     * @throws Exception
601 2
     * @throws InvalidArgumentException
602
     */
603 2
    public function getMe()
604
    {
605
        return User::fromResponse($this->call('getMe'));
606
    }
607
608
    /**
609 2
     * Use this method to receive incoming updates using long polling.
610
     * An Array of Update objects is returned.
611
     *
612
     * Notes
613
     * 1. This method will not work if an outgoing webhook is set up.
614
     * 2. In order to avoid getting duplicate updates, recalculate offset after each server response.
615
     *
616
     * @param int $offset
617
     * @param int $limit
618
     * @param int $timeout
619
     *
620
     * @return Update[]
621
     * @throws Exception
622
     * @throws InvalidArgumentException
623
     */
624
    public function getUpdates($offset = 0, $limit = 100, $timeout = 0)
625
    {
626
        $updates = ArrayOfUpdates::fromResponse($this->call('getUpdates', [
627
            'offset' => $offset,
628
            'limit' => $limit,
629
            'timeout' => $timeout,
630
        ]));
631
632
        if ($this->tracker instanceof Botan) {
633
            foreach ($updates as $update) {
634
                $this->trackUpdate($update);
635
            }
636
        }
637
638
        return $updates;
639
    }
640
641
    /**
642
     * Use this method to send point on the map. On success, the sent Message is returned.
643
     *
644
     * @param int|string $chatId
645
     * @param float $latitude
646
     * @param float $longitude
647
     * @param int|null $replyToMessageId
648
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
649
     * @param bool $disableNotification
650
     * @param null|int $livePeriod
651
     * @param int|null $messageThreadId
652
     * @param bool|null $protectContent
653
     * @param bool|null $allowSendingWithoutReply
654
     *
655
     * @return Message
656
     *
657
     * @throws Exception
658
     */
659
    public function sendLocation(
660
        $chatId,
661
        $latitude,
662
        $longitude,
663
        $replyToMessageId = null,
664
        $replyMarkup = null,
665
        $disableNotification = false,
666
        $livePeriod = null,
667
        $messageThreadId = null,
668
        $protectContent = null,
669
        $allowSendingWithoutReply = null
670
    ) {
671
        return Message::fromResponse($this->call('sendLocation', [
672
            'chat_id' => $chatId,
673
            'latitude' => $latitude,
674
            'longitude' => $longitude,
675
            'live_period' => $livePeriod,
676
            'message_thread_id' => $messageThreadId,
677
            'reply_to_message_id' => $replyToMessageId,
678
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
679
            'disable_notification' => (bool) $disableNotification,
680
            'protect_content' => (bool) $protectContent,
681
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
682
        ]));
683
    }
684
685
    /**
686
     * Use this method to edit live location messages sent by the bot or via the bot (for inline bots).
687
     * On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned.
688
     *
689
     * @param int|string $chatId
690
     * @param int $messageId
691
     * @param string $inlineMessageId
692
     * @param float $latitude
693
     * @param float $longitude
694
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
695
     *
696
     * @return Message|true
697
     *
698
     * @throws Exception
699
     */
700
    public function editMessageLiveLocation(
701
        $chatId,
702
        $messageId,
703
        $inlineMessageId,
704
        $latitude,
705
        $longitude,
706
        $replyMarkup = null
707
    ) {
708
        $response = $this->call('editMessageLiveLocation', [
709
            'chat_id' => $chatId,
710
            'message_id' => $messageId,
711
            'inline_message_id' => $inlineMessageId,
712
            'latitude' => $latitude,
713
            'longitude' => $longitude,
714
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
715
        ]);
716
        if ($response === true) {
717
            return true;
718
        }
719
720
        return Message::fromResponse($response);
721
    }
722
723
    /**
724
     * Use this method to stop updating a live location message sent by the bot or via the bot (for inline bots) before
725
     * live_period expires.
726
     * On success, if the message is not an inline message, the edited Message is returned, otherwise True is returned.
727
     *
728
     * @param int|string $chatId
729
     * @param int $messageId
730
     * @param string $inlineMessageId
731
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
732
     *
733
     * @return Message|true
734
     *
735
     * @throws Exception
736
     */
737
    public function stopMessageLiveLocation(
738
        $chatId,
739
        $messageId,
740
        $inlineMessageId,
741
        $replyMarkup = null
742
    ) {
743
        $response = $this->call('stopMessageLiveLocation', [
744
            'chat_id' => $chatId,
745
            'message_id' => $messageId,
746
            'inline_message_id' => $inlineMessageId,
747
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
748
        ]);
749
        if ($response === true) {
750
            return true;
751
        }
752
753
        return Message::fromResponse($response);
754
    }
755
756
    /**
757
     * Use this method to send information about a venue. On success, the sent Message is returned.
758
     *
759
     * @param int|string $chatId chat_id or @channel_name
760
     * @param float $latitude
761
     * @param float $longitude
762
     * @param string $title
763
     * @param string $address
764
     * @param string|null $foursquareId
765
     * @param int|null $replyToMessageId
766
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
767
     * @param bool $disableNotification
768
     * @param int|null $messageThreadId
769
     * @param bool|null $protectContent
770
     * @param bool|null $allowSendingWithoutReply
771
     *
772
     * @return Message
773
     * @throws Exception
774
     */
775
    public function sendVenue(
776
        $chatId,
777
        $latitude,
778
        $longitude,
779
        $title,
780
        $address,
781
        $foursquareId = null,
782
        $replyToMessageId = null,
783
        $replyMarkup = null,
784
        $disableNotification = false,
785
        $messageThreadId = null,
786
        $protectContent = null,
787
        $allowSendingWithoutReply = null
788
    ) {
789
        return Message::fromResponse($this->call('sendVenue', [
790
            'chat_id' => $chatId,
791
            'latitude' => $latitude,
792
            'longitude' => $longitude,
793
            'title' => $title,
794
            'address' => $address,
795
            'foursquare_id' => $foursquareId,
796
            'message_thread_id' => $messageThreadId,
797
            'reply_to_message_id' => $replyToMessageId,
798
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
799
            'disable_notification' => (bool) $disableNotification,
800
            'protect_content' => (bool) $protectContent,
801
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
802
        ]));
803
    }
804
805
    /**
806
     * Use this method to send .webp stickers. On success, the sent Message is returned.
807
     *
808
     * @param int|string $chatId chat_id or @channel_name
809
     * @param \CURLFile|string $sticker
810
     * @param int|null $replyToMessageId
811
     * @param InlineKeyboardMarkup|ReplyKeyboardMarkup|ReplyKeyboardRemove|ForceReply|null $replyMarkup
812
     * @param bool $disableNotification Sends the message silently. Users will receive a notification with no sound.
813
     * @param bool $protectContent Protects the contents of the sent message from forwarding and saving
814
     * @param bool $allowSendingWithoutReply Pass True if the message should be sent even if the specified replied-to message is not found
815
     * @param string|null $messageThreadId
816
     *
817
     * @return Message
818
     * @throws InvalidArgumentException
819
     * @throws Exception
820
     */
821
    public function sendSticker(
822
        $chatId,
823
        $sticker,
824
        $replyToMessageId = null,
825
        $replyMarkup = null,
826
        $disableNotification = false,
827
        $protectContent = false,
828
        $allowSendingWithoutReply = false,
829
        $messageThreadId = null
830
    ) {
831
        return Message::fromResponse($this->call('sendSticker', [
832
            'chat_id' => $chatId,
833
            'sticker' => $sticker,
834
            'message_thread_id' => $messageThreadId,
835
            'reply_to_message_id' => $replyToMessageId,
836
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
837
            'disable_notification' => (bool) $disableNotification,
838
            'protect_content' => (bool) $protectContent,
839
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
840
        ]));
841
    }
842
843
    /**
844
     * @param string $name Name of the sticker set
845
     * @return StickerSet
846
     * @throws InvalidArgumentException
847
     * @throws Exception
848
     */
849
    public function getStickerSet($name)
850
    {
851
        return StickerSet::fromResponse($this->call('getStickerSet', [
852
            'name' => $name,
853
        ]));
854
    }
855
856
    /**
857
     * @param array[] $customEmojiIds List of custom emoji identifiers.
858
     *                                At most 200 custom emoji identifiers can be specified.
859
     * @return StickerSet
860
     * @throws InvalidArgumentException
861
     * @throws Exception
862
     *
863
     * @author bernard-ng <[email protected]>
864
     */
865
    public function getCustomEmojiStickers($customEmojiIds = [])
866
    {
867
        return StickerSet::fromResponse($this->call('getCustomEmojiStickers', [
868
            'custom_emoji_ids' => $customEmojiIds,
869
        ]));
870
    }
871
872
    /**
873
     * Use this method to create a new sticker set owned by a user.
874
     * The bot will be able to edit the sticker set thus created.
875
     * You must use exactly one of the fields png_sticker, tgs_sticker, or webm_sticker.
876
     * Returns True on success.
877
     *
878
     * @param int $userId User identifier of created sticker set owner
879
     * @param string $pngSticker PNG image with the sticker, must be up to 512 kilobytes in size,
880
     *                           dimensions must not exceed 512px, and either width or height must be exactly 512px.
881
     *
882
     * @return File
883
     *
884
     * @throws InvalidArgumentException
885
     * @throws Exception
886
     */
887
    public function uploadStickerFile($userId, $pngSticker)
888
    {
889
        return File::fromResponse($this->call('uploadStickerFile', [
890
            'user_id' => $userId,
891
            'png_sticker' => $pngSticker,
892
        ]));
893
    }
894
895
    /**
896
     * Use this method to create a new sticker set owned by a user.
897
     * The bot will be able to edit the sticker set thus created.
898
     * You must use exactly one of the fields png_sticker, tgs_sticker, or webm_sticker. Returns True on success.
899
     *
900
     * @param int $userId User identifier of created sticker set owner
901
     * @param string $name Short name of sticker set, to be used in t.me/addstickers/ URLs (e.g., animals).
902
     *                     Can contain only english letters, digits and underscores. Must begin with a letter,
903
     *                     can't contain consecutive underscores and must end in “_by_<bot username>”.
904
     *                     <bot_username> is case insensitive. 1-64 characters.
905
     * @param string $title Sticker set title, 1-64 characters
906
     * @param string $pngSticker PNG image with the sticker, must be up to 512 kilobytes in size,
907
     *                           dimensions must not exceed 512px, and either width or height must be exactly 512px.
908
     *                           Pass a file_id as a String to send a file that already exists on the Telegram servers,
909
     *                           pass an HTTP URL as a String for Telegram to get a file from the Internet,
910
     *                           or upload a new one using multipart/form-data.
911
     * @param string $tgsSticker TGS animation with the sticker, uploaded using multipart/form-data.
912
     *                           See https://core.telegram.org/animated_stickers#technical-requirements for technical requirements
913
     * @param string $webmSticker WebP animation with the sticker, uploaded using multipart/form-data.
914
     *                            See https://core.telegram.org/animated_stickers#technical-requirements for technical requirements
915
     * @param string $stickerType Sticker type, one of “png”, “tgs”, or “webp”
916
     * @param string $emojis One or more emoji corresponding to the sticker
917
     * @param MaskPosition|null $maskPosition A JSON-serialized object for position where the mask should be placed on faces
918
     * @param array<string, \CURLFile|\CURLStringFile> $attachments Attachments to use in attach://<attachment>
919
     *
920
     * @throws InvalidArgumentException
921
     * @throws Exception
922
     *
923
     * @return bool
924
     *
925
     * @author bernard-ng <[email protected]>
926
     */
927
    public function createNewStickerSet(
928
        $userId,
929
        $name,
930
        $title,
931
        $emojis,
932
        $pngSticker,
933
        $tgsSticker = null,
934
        $webmSticker = null,
935
        $stickerType = null,
936
        $maskPosition = null,
937
        $attachments = []
938
    ) {
939
        return $this->call('createNewStickerSet', [
940
            'user_id' => $userId,
941
            'name' => $name,
942
            'title' => $title,
943
            'png_sticker' => $pngSticker,
944
            'tgs_sticker' => $tgsSticker,
945
            'webm_sticker' => $webmSticker,
946
            'sticker_type' => $stickerType,
947
            'emojis' => $emojis,
948
            'mask_position' => is_null($maskPosition) ? $maskPosition : $maskPosition->toJson(),
949
        ] + $attachments);
950
    }
951
952
    /**
953
     * Use this method to add a new sticker to a set created by the bot.
954
     * You must use exactly one of the fields png_sticker, tgs_sticker, or webm_sticker.
955
     * Animated stickers can be added to animated sticker sets and only to them.
956
     * Animated sticker sets can have up to 50 stickers.
957
     * Static sticker sets can have up to 120 stickers. Returns True on success.
958
     *
959
     * @param string $userId
960
     * @param string $name
961
     * @param string $emojis
962
     * @param string $pngSticker
963
     * @param string|null $tgsSticker
964
     * @param string|null $webmSticker
965
     * @param MaskPosition|null $maskPosition
966
     * @param array<string, \CURLFile|\CURLStringFile> $attachments Attachments to use in attach://<attachment>
967
     *
968
     * @return bool
969
     * @throws Exception
970
     * @throws HttpException
971
     * @throws InvalidJsonException
972
     */
973
    public function addStickerToSet(
974
        $userId,
975
        $name,
976
        $emojis,
977
        $pngSticker,
978
        $tgsSticker = null,
979
        $webmSticker = null,
980
        $maskPosition = null,
981
        $attachments = []
982
    ) {
983
        return $this->call('addStickerToSet', [
984
            'user_id' => $userId,
985
            'name' => $name,
986
            'png_sticker' => $pngSticker,
987
            'tgs_sticker' => $tgsSticker,
988
            'webm_sticker' => $webmSticker,
989
            'emojis' => $emojis,
990
            'mask_position' => is_null($maskPosition) ? $maskPosition : $maskPosition->toJson(),
991
        ] + $attachments);
992
    }
993
994
    /**
995
     * Use this method to move a sticker in a set created by the bot to a specific position.
996
     * Returns True on success.
997
     *
998
     * @param string $sticker File identifier of the sticker
999
     * @param int $position New sticker position in the set, zero-based
1000
     *
1001
     * @return bool
1002
     *
1003
     * @throws InvalidArgumentException
1004
     * @throws Exception
1005
     */
1006
    public function setStickerPositionInSet($sticker, $position)
1007
    {
1008
        return $this->call('setStickerPositionInSet', [
1009
            'sticker' => $sticker,
1010
            'position' => $position,
1011
        ]);
1012
    }
1013
1014
    /**
1015
     * Use this method to delete a sticker from a set created by the bot.
1016
     * Returns True on success.
1017
     *
1018
     * @param string $name Sticker set name
1019
     * @param string $userId User identifier of sticker set owner
1020
     * @param File|null $thumbnail A PNG image with the thumbnail,
1021
     *                             must be up to 128 kilobytes in size and have width and height exactly 100px,
1022
     *                             or a TGS animation with the thumbnail up to 32 kilobytes in size
1023
     *
1024
     * @return bool
1025
     *
1026
     * @throws InvalidArgumentException
1027
     * @throws Exception
1028
     */
1029
    public function setStickerSetThumbnail($name, $userId, $thumbnail = null)
1030
    {
1031
        return $this->call('setStickerSetThumb', [
1032
            'name' => $name,
1033
            'user_id' => $userId,
1034
            'thumbnail' => $thumbnail,
1035
        ]);
1036
    }
1037
1038
    /**
1039
     * @deprecated Use setStickerSetThumbnail
1040
     *
1041
     * Use this method to delete a sticker from a set created by the bot.
1042
     * Returns True on success.
1043
     *
1044
     * @param string $name Sticker set name
1045
     * @param string $userId User identifier of sticker set owner
1046
     * @param File|null $thumb A PNG image with the thumbnail,
1047
     *                         must be up to 128 kilobytes in size and have width and height exactly 100px,
1048
     *                         or a TGS animation with the thumbnail up to 32 kilobytes in size
1049
     *
1050
     * @return bool
1051
     *
1052
     * @throws InvalidArgumentException
1053
     * @throws Exception
1054
     */
1055
    public function setStickerSetThumb($name, $userId, $thumb = null)
1056
    {
1057
        return $this->setStickerSetThumbnail($name, $userId, $thumb);
1058
    }
1059
1060
    /**
1061
     * Use this method to send video files,
1062
     * Telegram clients support mp4 videos (other formats may be sent as Document).
1063
     * On success, the sent Message is returned.
1064
     *
1065
     * @param int|string $chatId chat_id or @channel_name
1066
     * @param \CURLFile|string $video
1067
     * @param int|null $duration
1068
     * @param string|null $caption
1069
     * @param int|null $replyToMessageId
1070
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
1071
     * @param bool $disableNotification
1072
     * @param bool $supportsStreaming Pass True, if the uploaded video is suitable for streaming
1073
     * @param string|null $parseMode
1074
     * @param int|null $messageThreadId
1075
     * @param bool|null $protectContent
1076
     * @param bool|null $allowSendingWithoutReply
1077
     * @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...
1078
     *
1079
     * @return Message
1080
     * @throws InvalidArgumentException
1081
     * @throws Exception
1082
     */
1083
    public function sendVideo(
1084
        $chatId,
1085
        $video,
1086
        $duration = null,
1087
        $caption = null,
1088
        $replyToMessageId = null,
1089
        $replyMarkup = null,
1090
        $disableNotification = false,
1091
        $supportsStreaming = false,
1092
        $parseMode = null,
1093
        $messageThreadId = null,
1094
        $protectContent = null,
1095
        $allowSendingWithoutReply = null,
1096
        $thumbnail = null
1097
    ) {
1098
        return Message::fromResponse($this->call('sendVideo', [
1099
            'chat_id' => $chatId,
1100
            'video' => $video,
1101
            'duration' => $duration,
1102
            'caption' => $caption,
1103
            'message_thread_id' => $messageThreadId,
1104
            'reply_to_message_id' => $replyToMessageId,
1105
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1106
            'disable_notification' => (bool) $disableNotification,
1107
            'supports_streaming' => (bool) $supportsStreaming,
1108
            'parse_mode' => $parseMode,
1109
            'protect_content' => (bool) $protectContent,
1110
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1111
            'thumbnail' => $thumbnail,
1112
        ]));
1113
    }
1114
1115
    /**
1116
     * Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound),
1117
     * On success, the sent Message is returned.
1118
     * Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future.
1119
     *
1120
     * @param int|string $chatId chat_id or @channel_name
1121
     * @param \CURLFile|string $animation
1122
     * @param int|null $duration
1123
     * @param string|null $caption
1124
     * @param int|null $replyToMessageId
1125
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
1126
     * @param bool $disableNotification
1127
     * @param string|null $parseMode,
1128
     * @param int|null $messageThreadId
1129
     * @param bool|null $protectContent
1130
     * @param bool|null $allowSendingWithoutReply
1131
     * @param \CURLFile|\CURLStringFile|string|null $thumbnail
1132
     *
1133
     * @return Message
1134
     * @throws InvalidArgumentException
1135
     * @throws Exception
1136
     */
1137
    public function sendAnimation(
1138
        $chatId,
1139
        $animation,
1140
        $duration = null,
1141
        $caption = null,
1142
        $replyToMessageId = null,
1143
        $replyMarkup = null,
1144
        $disableNotification = false,
1145
        $parseMode = null,
1146
        $messageThreadId = null,
1147
        $protectContent = null,
1148
        $allowSendingWithoutReply = null,
1149
        $thumbnail = null
1150
    ) {
1151
        return Message::fromResponse($this->call('sendAnimation', [
1152
            'chat_id' => $chatId,
1153
            'animation' => $animation,
1154
            'duration' => $duration,
1155
            'caption' => $caption,
1156
            'message_thread_id' => $messageThreadId,
1157
            'reply_to_message_id' => $replyToMessageId,
1158
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1159
            'disable_notification' => (bool) $disableNotification,
1160
            'parse_mode' => $parseMode,
1161
            'protect_content' => (bool) $protectContent,
1162
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1163
            'thumbnail' => $thumbnail,
1164
        ]));
1165
    }
1166
1167
    /**
1168
     * Use this method to send audio files,
1169
     * if you want Telegram clients to display the file as a playable voice message.
1170
     * For this to work, your audio must be in an .ogg file encoded with OPUS
1171
     * (other formats may be sent as Audio or Document).
1172
     * On success, the sent Message is returned.
1173
     * Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future.
1174
     *
1175
     * @param int|string $chatId chat_id or @channel_name
1176
     * @param \CURLFile|string $voice
1177
     * @param string $caption Voice message caption, 0-1024 characters after entities parsing
1178
     * @param int|null $duration
1179
     * @param int|null $replyToMessageId
1180
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
1181
     * @param bool $disableNotification
1182
     * @param bool $allowSendingWithoutReply Pass True, if the message should be sent even if the specified
1183
     *                                       replied-to message is not found
1184
     * @param string|null $parseMode
1185
     * @param int|null $messageThreadId
1186
     * @param bool|null $protectContent
1187
     *
1188
     * @return Message
1189
     * @throws InvalidArgumentException
1190
     * @throws Exception
1191
     */
1192
    public function sendVoice(
1193
        $chatId,
1194
        $voice,
1195
        $caption = null,
1196
        $duration = null,
1197
        $replyToMessageId = null,
1198
        $replyMarkup = null,
1199
        $disableNotification = false,
1200
        $allowSendingWithoutReply = false,
1201
        $parseMode = null,
1202
        $messageThreadId = null,
1203
        $protectContent = null
1204
    ) {
1205
        return Message::fromResponse($this->call('sendVoice', [
1206
            'chat_id' => $chatId,
1207
            'voice' => $voice,
1208
            'caption' => $caption,
1209
            'duration' => $duration,
1210
            'message_thread_id' => $messageThreadId,
1211
            'reply_to_message_id' => $replyToMessageId,
1212
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1213
            'disable_notification' => (bool) $disableNotification,
1214
            'allow_sending_without_reply' => $allowSendingWithoutReply,
1215
            'parse_mode' => $parseMode,
1216
            'protect_content' => (bool) $protectContent,
1217
        ]));
1218
    }
1219
1220
    /**
1221
     * Use this method to forward messages of any kind. Service messages can't be forwarded.
1222
     * On success, the sent Message is returned.
1223
     *
1224
     * @param int|string $chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername)
1225
     * @param int $fromChatId Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername)
1226
     * @param string $messageId Message identifier in the chat specified in from_chat_id
1227
     * @param bool $protectContent Protects the contents of the forwarded message from forwarding and saving
1228
     * @param bool $disableNotification Sends the message silently. Users will receive a notification with no sound.
1229
     * @param int|null $messageThreadId Unique identifier for the target message thread (topic) of the forum; for forum supergroups only
1230
     *
1231
     * @return Message
1232
     * @throws Exception
1233
     * @throws HttpException
1234
     * @throws InvalidJsonException
1235
     */
1236
    public function forwardMessage(
1237
        $chatId,
1238
        $fromChatId,
1239
        $messageId,
1240
        $protectContent = false,
1241
        $disableNotification = false,
1242
        $messageThreadId = null
1243
    ) {
1244
        return Message::fromResponse($this->call('forwardMessage', [
1245
            'chat_id' => $chatId,
1246
            'from_chat_id' => $fromChatId,
1247
            'message_id' => $messageId,
1248
            'message_thread_id' => $messageThreadId,
1249
            'protect_content' => $protectContent,
1250
            'disable_notification' => (bool) $disableNotification,
1251
        ]));
1252
    }
1253
1254
    /**
1255
     * Use this method to send audio files,
1256
     * if you want Telegram clients to display them in the music player.
1257
     * Your audio must be in the .mp3 format.
1258
     * On success, the sent Message is returned.
1259
     * Bots can currently send audio files of up to 50 MB in size, this limit may be changed in the future.
1260
     *
1261
     * For backward compatibility, when the fields title and performer are both empty
1262
     * and the mime-type of the file to be sent is not audio/mpeg, the file will be sent as a playable voice message.
1263
     * For this to work, the audio must be in an .ogg file encoded with OPUS.
1264
     * This behavior will be phased out in the future. For sending voice messages, use the sendVoice method instead.
1265
     *
1266
     * @param int|string $chatId chat_id or @channel_name
1267
     * @param \CURLFile|string $audio
1268
     * @param int|null $duration
1269
     * @param string|null $performer
1270
     * @param string|null $title
1271
     * @param int|null $replyToMessageId
1272
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
1273
     * @param bool $disableNotification
1274
     * @param string|null $parseMode
1275
     * @param bool|null $protectContent
1276
     * @param bool|null $allowSendingWithoutReply
1277
     * @param \CURLFile|\CURLStringFile|string|null $thumbnail
1278
     *
1279
     * @return Message
1280
     * @throws InvalidArgumentException
1281
     * @throws Exception
1282
     * @deprecated since 20th February. Removed backward compatibility from the method sendAudio.
1283
     * Voice messages now must be sent using the method sendVoice.
1284
     * There is no more need to specify a non-empty title or performer while sending the audio by file_id.
1285
     *
1286
     */
1287
    public function sendAudio(
1288
        $chatId,
1289
        $audio,
1290
        $duration = null,
1291
        $performer = null,
1292
        $title = null,
1293
        $replyToMessageId = null,
1294
        $replyMarkup = null,
1295
        $disableNotification = false,
1296
        $parseMode = null,
1297
        $protectContent = null,
1298
        $allowSendingWithoutReply = null,
1299
        $thumbnail = null
1300
    ) {
1301
        return Message::fromResponse($this->call('sendAudio', [
1302
            'chat_id' => $chatId,
1303
            'audio' => $audio,
1304
            'duration' => $duration,
1305
            'performer' => $performer,
1306
            'title' => $title,
1307
            'reply_to_message_id' => $replyToMessageId,
1308
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1309
            'disable_notification' => (bool) $disableNotification,
1310
            'parse_mode' => $parseMode,
1311
            'protect_content' => (bool) $protectContent,
1312
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1313
            'thumbnail' => $thumbnail,
1314
        ]));
1315
    }
1316
1317
    /**
1318
     * Use this method to send photos. On success, the sent Message is returned.
1319
     *
1320
     * @param int|string $chatId chat_id or @channel_name
1321
     * @param \CURLFile|string $photo
1322
     * @param string|null $caption
1323
     * @param int|null $replyToMessageId
1324
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
1325
     * @param bool $disableNotification
1326
     * @param string|null $parseMode
1327
     * @param int|null $messageThreadId
1328
     * @param bool|null $protectContent
1329
     * @param bool|null $allowSendingWithoutReply
1330
     *
1331
     * @return Message
1332
     * @throws InvalidArgumentException
1333
     * @throws Exception
1334
     */
1335
    public function sendPhoto(
1336
        $chatId,
1337
        $photo,
1338
        $caption = null,
1339
        $replyToMessageId = null,
1340
        $replyMarkup = null,
1341
        $disableNotification = false,
1342
        $parseMode = null,
1343
        $messageThreadId = null,
1344
        $protectContent = null,
1345
        $allowSendingWithoutReply = null
1346
    ) {
1347
        return Message::fromResponse($this->call('sendPhoto', [
1348
            'chat_id' => $chatId,
1349
            'photo' => $photo,
1350
            'caption' => $caption,
1351
            'message_thread_id' => $messageThreadId,
1352
            'reply_to_message_id' => $replyToMessageId,
1353
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1354
            'disable_notification' => (bool) $disableNotification,
1355
            'parse_mode' => $parseMode,
1356
            'protect_content' => (bool) $protectContent,
1357
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1358
        ]));
1359
    }
1360
1361
    /**
1362
     * Use this method to send general files. On success, the sent Message is returned.
1363
     * Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future.
1364
     *
1365
     * @param int|string $chatId chat_id or @channel_name
1366
     * @param \CURLFile|\CURLStringFile|string $document
1367
     * @param string|null $caption
1368
     * @param int|null $replyToMessageId
1369
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
1370
     * @param bool $disableNotification
1371
     * @param string|null $parseMode
1372
     * @param int|null $messageThreadId
1373
     * @param bool|null $protectContent
1374
     * @param bool|null $allowSendingWithoutReply
1375
     * @param \CURLFile|\CURLStringFile|string|null $thumbnail
1376
     *
1377
     * @return Message
1378
     * @throws InvalidArgumentException
1379
     * @throws Exception
1380
     */
1381
    public function sendDocument(
1382
        $chatId,
1383
        $document,
1384
        $caption = null,
1385
        $replyToMessageId = null,
1386
        $replyMarkup = null,
1387
        $disableNotification = false,
1388
        $parseMode = null,
1389
        $messageThreadId = null,
1390
        $protectContent = null,
1391
        $allowSendingWithoutReply = null,
1392
        $thumbnail = null
1393
    ) {
1394
        return Message::fromResponse($this->call('sendDocument', [
1395
            'chat_id' => $chatId,
1396
            'document' => $document,
1397
            'caption' => $caption,
1398
            'message_thread_id' => $messageThreadId,
1399
            'reply_to_message_id' => $replyToMessageId,
1400
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1401
            'disable_notification' => (bool) $disableNotification,
1402
            'parse_mode' => $parseMode,
1403
            'protect_content' => (bool) $protectContent,
1404
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1405
            'thumbnail' => $thumbnail,
1406
        ]));
1407
    }
1408
1409
    /**
1410
     * Use this method to get basic info about a file and prepare it for downloading.
1411
     * For the moment, bots can download files of up to 20MB in size.
1412
     * On success, a File object is returned.
1413
     * The file can then be downloaded via the link https://api.telegram.org/file/bot<token>/<file_path>,
1414
     * where <file_path> is taken from the response.
1415
     * It is guaranteed that the link will be valid for at least 1 hour.
1416
     * When the link expires, a new one can be requested by calling getFile again.
1417
     *
1418
     * @param string $fileId
1419
     *
1420
     * @return File
1421
     * @throws InvalidArgumentException
1422
     * @throws Exception
1423
     */
1424
    public function getFile($fileId)
1425
    {
1426
        return File::fromResponse($this->call('getFile', ['file_id' => $fileId]));
1427
    }
1428
1429
    /**
1430
     * Get file contents via cURL
1431
     *
1432
     * @param string $fileId
1433
     *
1434
     * @return string
1435
     *
1436
     * @throws HttpException
1437
     * @throws Exception
1438
     */
1439
    public function downloadFile($fileId)
1440
    {
1441
        $file = $this->getFile($fileId);
1442
        $options = [
1443
            CURLOPT_HEADER => 0,
1444
            CURLOPT_HTTPGET => 1,
1445
            CURLOPT_RETURNTRANSFER => 1,
1446
            CURLOPT_URL => $this->getFileUrl().'/'.$file->getFilePath(),
1447
        ];
1448
1449
        return $this->executeCurl($options);
1450
    }
1451
1452
    /**
1453
     * Use this method to send answers to an inline query. On success, True is returned.
1454
     * No more than 50 results per query are allowed.
1455
     *
1456
     * @param string $inlineQueryId
1457
     * @param AbstractInlineQueryResult[] $results
1458
     * @param int $cacheTime
1459
     * @param bool $isPersonal
1460
     * @param string $nextOffset
1461
     * @param string $switchPmText
1462
     * @param string $switchPmParameter
1463
     *
1464
     * @return mixed
1465
     * @throws Exception
1466
     */
1467
    public function answerInlineQuery(
1468
        $inlineQueryId,
1469
        $results,
1470
        $cacheTime = 300,
1471
        $isPersonal = false,
1472
        $nextOffset = '',
1473
        $switchPmText = null,
1474
        $switchPmParameter = null
1475
    ) {
1476
        $results = array_map(
1477
            /**
1478
             * @param AbstractInlineQueryResult $item
1479
             * @return array
1480
             */
1481
            function ($item) {
1482
                /** @var array $array */
1483
                $array = $item->toJson(true);
1484
1485
                return $array;
1486
            },
1487
            $results
1488
        );
1489
1490
        return $this->call('answerInlineQuery', [
1491
            'inline_query_id' => $inlineQueryId,
1492
            'results' => json_encode($results),
1493
            'cache_time' => $cacheTime,
1494
            'is_personal' => $isPersonal,
1495
            'next_offset' => $nextOffset,
1496
            'switch_pm_text' => $switchPmText,
1497
            'switch_pm_parameter' => $switchPmParameter,
1498
        ]);
1499
    }
1500
1501
    /**
1502
     * Use this method to kick a user from a group or a supergroup.
1503
     * In the case of supergroups, the user will not be able to return to the group
1504
     * on their own using invite links, etc., unless unbanned first.
1505
     * The bot must be an administrator in the group for this to work. Returns True on success.
1506
     *
1507
     * @param int|string $chatId Unique identifier for the target group
1508
     *                           or username of the target supergroup (in the format @supergroupusername)
1509
     * @param int $userId Unique identifier of the target user
1510
     * @param null|int $untilDate Date when the user will be unbanned, unix time.
1511
     *                            If user is banned for more than 366 days or less than 30 seconds from the current time
1512
     *                            they are considered to be banned forever
1513
     *
1514
     * @return bool
1515
     * @throws Exception
1516
     */
1517
    public function kickChatMember($chatId, $userId, $untilDate = null)
1518
    {
1519
        return $this->call('kickChatMember', [
1520
            'chat_id' => $chatId,
1521
            'user_id' => $userId,
1522
            'until_date' => $untilDate
1523
        ]);
1524
    }
1525
1526
    /**
1527
     * Use this method to unban a previously kicked user in a supergroup.
1528
     * The user will not return to the group automatically, but will be able to join via link, etc.
1529
     * The bot must be an administrator in the group for this to work. Returns True on success.
1530
     *
1531
     * @param int|string $chatId Unique identifier for the target group
1532
     *                           or username of the target supergroup (in the format @supergroupusername)
1533
     * @param int $userId Unique identifier of the target user
1534
     *
1535
     * @return bool
1536
     * @throws Exception
1537
     */
1538
    public function unbanChatMember($chatId, $userId)
1539
    {
1540
        return $this->call('unbanChatMember', [
1541
            'chat_id' => $chatId,
1542
            'user_id' => $userId,
1543
        ]);
1544
    }
1545
1546
    /**
1547
     * Use this method to send answers to callback queries sent from inline keyboards.
1548
     * The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.
1549
     *
1550
     * @param string $callbackQueryId
1551
     * @param string|null $text
1552
     * @param bool $showAlert
1553
     * @param string|null $url
1554
     * @param int $cacheTime
1555
     *
1556
     * @return bool
1557
     * @throws Exception
1558
     */
1559
    public function answerCallbackQuery($callbackQueryId, $text = null, $showAlert = false, $url = null, $cacheTime = 0)
1560
    {
1561
        return $this->call('answerCallbackQuery', [
1562
            'callback_query_id' => $callbackQueryId,
1563
            'text' => $text,
1564
            'show_alert' => (bool) $showAlert,
1565
            'url' => $url,
1566
            'cache_time' => $cacheTime
1567
        ]);
1568
    }
1569
1570
    /**
1571
     * Use this method to change the list of the bot's commands. Returns True on success.
1572
     *
1573
     * @param ArrayOfBotCommand|BotCommand[] $commands
1574
     * @param string|null $scope
1575
     * @param string|null $languageCode
1576
     *
1577
     * @return mixed
1578
     * @throws Exception
1579
     * @throws HttpException
1580
     * @throws InvalidJsonException
1581
     */
1582
    public function setMyCommands($commands, $scope = null, $languageCode = null)
1583
    {
1584
        if (!$commands instanceof ArrayOfBotCommand) {
1585
            @trigger_error(sprintf('Passing array of BotCommand to "%s::%s" is deprecated. Use %s', __CLASS__, __METHOD__, ArrayOfBotCommand::class), \E_USER_DEPRECATED);
1586
            $commands = new ArrayOfBotCommand($commands);
1587
        }
1588
1589
        return $this->call('setMyCommands', [
1590
            'commands' => $commands->toJson(),
1591
            'scope' => $scope,
1592
            'language_code' => $languageCode,
1593
        ]);
1594
    }
1595
1596
    /**
1597
     * Use this method to get the current list of the bot's commands. Requires no parameters.
1598
     * Returns Array of BotCommand on success.
1599
     *
1600
     * @return ArrayOfBotCommand
1601
     *
1602
     * @throws Exception
1603
     * @throws HttpException
1604
     * @throws InvalidJsonException
1605
     */
1606
    public function getMyCommands()
1607
    {
1608
        return ArrayOfBotCommand::fromResponse($this->call('getMyCommands'));
1609
    }
1610
1611 9
    /**
1612
     * Use this method to edit text messages sent by the bot or via the bot
1613 9
     * On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned.
1614 9
     *
1615
     * @param int|string $chatId
1616
     * @param int $messageId
1617
     * @param string $text
1618
     * @param string $inlineMessageId
1619
     * @param string|null $parseMode
1620
     * @param bool $disablePreview
1621
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
1622
     *
1623
     * @return Message|true
1624
     * @throws Exception
1625
     */
1626
    public function editMessageText(
1627
        $chatId,
1628
        $messageId,
1629
        $text,
1630
        $parseMode = null,
1631
        $disablePreview = false,
1632
        $replyMarkup = null,
1633
        $inlineMessageId = null
1634
    ) {
1635
        $response = $this->call('editMessageText', [
1636
            'chat_id' => $chatId,
1637
            'message_id' => $messageId,
1638
            'text' => $text,
1639
            'inline_message_id' => $inlineMessageId,
1640
            'parse_mode' => $parseMode,
1641
            'disable_web_page_preview' => $disablePreview,
1642
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1643
        ]);
1644
        if ($response === true) {
1645
            return true;
1646
        }
1647
1648
        return Message::fromResponse($response);
1649
    }
1650
1651
    /**
1652
     * Use this method to edit text messages sent by the bot or via the bot
1653
     * On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned.
1654
     *
1655
     * @param int|string $chatId
1656
     * @param int $messageId
1657
     * @param string|null $caption
1658
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
1659
     * @param string $inlineMessageId
1660
     * @param string|null $parseMode
1661
     *
1662
     * @return Message|true
1663
     * @throws InvalidArgumentException
1664
     * @throws Exception
1665
     */
1666
    public function editMessageCaption(
1667
        $chatId,
1668
        $messageId,
1669
        $caption = null,
1670
        $replyMarkup = null,
1671
        $inlineMessageId = null,
1672
        $parseMode = null
1673
    ) {
1674
        $response = $this->call('editMessageCaption', [
1675
            'chat_id' => $chatId,
1676
            'message_id' => $messageId,
1677
            'inline_message_id' => $inlineMessageId,
1678
            'caption' => $caption,
1679
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1680
            'parse_mode' => $parseMode
1681
        ]);
1682
        if ($response === true) {
1683
            return true;
1684
        }
1685
1686
        return Message::fromResponse($response);
1687
    }
1688
1689
    /**
1690
     * Use this method to edit animation, audio, document, photo, or video messages.
1691
     * If a message is a part of a message album, then it can be edited only to a photo or a video.
1692
     * Otherwise, message type can be changed arbitrarily.
1693
     * When inline message is edited, new file can't be uploaded.
1694
     * Use previously uploaded file via its file_id or specify a URL.
1695
     * On success, if the edited message was sent by the bot, the edited Message is returned, otherwise True is returned
1696
     *
1697
     * @param string $chatId
1698
     * @param string $messageId
1699
     * @param InputMedia $media
1700
     * @param string|null $inlineMessageId
1701
     * @param InlineKeyboardMarkup|null $replyMarkup
1702
     * @param array<string, \CURLFile|\CURLStringFile> $attachments Attachments to use in attach://<attachment>
1703
     *
1704
     * @return Message|true
1705
     *
1706
     * @throws Exception
1707
     * @throws HttpException
1708
     * @throws InvalidJsonException
1709
     */
1710
    public function editMessageMedia(
1711
        $chatId,
1712
        $messageId,
1713
        InputMedia $media,
1714
        $inlineMessageId = null,
1715
        $replyMarkup = null,
1716
        $attachments = []
1717
    ) {
1718
        $response = $this->call('editMessageMedia', [
1719
            'chat_id' => $chatId,
1720
            'message_id' => $messageId,
1721
            'inline_message_id' => $inlineMessageId,
1722
            'media' => $media->toJson(),
1723
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1724
        ] + $attachments);
1725
        if ($response === true) {
1726
            return true;
1727
        }
1728
1729
        return Message::fromResponse($response);
1730
    }
1731
1732
    /**
1733
     * Use this method to edit only the reply markup of messages sent by the bot or via the bot
1734
     * On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned.
1735
     *
1736
     * @param int|string $chatId
1737
     * @param int $messageId
1738
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
1739
     * @param string $inlineMessageId
1740
     *
1741
     * @return Message|true
1742
     * @throws Exception
1743
     */
1744
    public function editMessageReplyMarkup(
1745
        $chatId,
1746
        $messageId,
1747
        $replyMarkup = null,
1748
        $inlineMessageId = null
1749
    ) {
1750
        $response = $this->call('editMessageReplyMarkup', [
1751
            'chat_id' => $chatId,
1752
            'message_id' => $messageId,
1753
            'inline_message_id' => $inlineMessageId,
1754
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1755
        ]);
1756
        if ($response === true) {
1757
            return true;
1758
        }
1759
1760
        return Message::fromResponse($response);
1761
    }
1762
1763
    /**
1764
     * Use this method to delete a message, including service messages, with the following limitations:
1765
     *  - A message can only be deleted if it was sent less than 48 hours ago.
1766
     *  - Bots can delete outgoing messages in groups and supergroups.
1767
     *  - Bots granted can_post_messages permissions can delete outgoing messages in channels.
1768
     *  - If the bot is an administrator of a group, it can delete any message there.
1769
     *  - If the bot has can_delete_messages permission in a supergroup or a channel, it can delete any message there.
1770
     *
1771
     * @param int|string $chatId
1772
     * @param int $messageId
1773
     *
1774
     * @return bool
1775
     * @throws Exception
1776
     */
1777
    public function deleteMessage($chatId, $messageId)
1778
    {
1779
        return $this->call('deleteMessage', [
1780
            'chat_id' => $chatId,
1781
            'message_id' => $messageId,
1782
        ]);
1783
    }
1784
1785
    /**
1786
     * Close curl
1787
     */
1788
    public function __destruct()
1789
    {
1790
        curl_close($this->curl);
1791
    }
1792
1793
    /**
1794
     * @return string
1795
     */
1796
    public function getUrl()
1797
    {
1798
        return self::URL_PREFIX.$this->token;
1799
    }
1800
1801
    /**
1802
     * @return string
1803
     */
1804
    public function getFileUrl()
1805
    {
1806
        return self::FILE_URL_PREFIX.$this->token;
1807
    }
1808
1809
    /**
1810
     * @param Update $update
1811
     * @param string $eventName
1812
     *
1813
     * @throws Exception
1814
     *
1815
     * @return void
1816
     */
1817
    public function trackUpdate(Update $update, $eventName = 'Message')
1818
    {
1819
        if (!in_array($update->getUpdateId(), $this->trackedEvents)) {
1820
            $message = $update->getMessage();
1821
            if (!$message) {
1822
                return;
1823
            }
1824
            $this->trackedEvents[] = $update->getUpdateId();
1825
1826
            $this->track($message, $eventName);
1827
1828
            if (count($this->trackedEvents) > self::MAX_TRACKED_EVENTS) {
1829
                $this->trackedEvents = array_slice($this->trackedEvents, (int) round(self::MAX_TRACKED_EVENTS / 4));
1830
            }
1831
        }
1832
    }
1833
1834
    /**
1835
     * Wrapper for tracker
1836
     *
1837
     * @param Message $message
1838
     * @param string $eventName
1839
     *
1840
     * @throws Exception
1841
     *
1842
     * @return void
1843
     */
1844
    public function track(Message $message, $eventName = 'Message')
1845
    {
1846
        if ($this->tracker instanceof Botan) {
1847
            $this->tracker->track($message, $eventName);
1848
        }
1849
    }
1850
1851
    /**
1852
     * Use this method to send invoices. On success, the sent Message is returned.
1853
     *
1854
     * @param int|string $chatId
1855
     * @param string $title
1856
     * @param string $description
1857
     * @param string $payload
1858
     * @param string $providerToken
1859
     * @param string $startParameter
1860
     * @param string $currency
1861
     * @param array $prices
1862
     * @param bool $isFlexible
1863
     * @param string|null $photoUrl
1864
     * @param int|null $photoSize
1865
     * @param int|null $photoWidth
1866
     * @param int|null $photoHeight
1867
     * @param bool $needName
1868
     * @param bool $needPhoneNumber
1869
     * @param bool $needEmail
1870
     * @param bool $needShippingAddress
1871
     * @param int|null $replyToMessageId
1872
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
1873
     * @param bool $disableNotification
1874
     * @param string|null $providerData
1875
     * @param bool $sendPhoneNumberToProvider
1876
     * @param bool $sendEmailToProvider
1877
     * @param int|null $messageThreadId
1878
     * @param bool|null $protectContent
1879
     * @param bool|null $allowSendingWithoutReply
1880
     *
1881
     * @return Message
1882
     * @throws Exception
1883
     */
1884
    public function sendInvoice(
1885
        $chatId,
1886
        $title,
1887
        $description,
1888
        $payload,
1889
        $providerToken,
1890
        $startParameter,
1891
        $currency,
1892
        $prices,
1893
        $isFlexible = false,
1894
        $photoUrl = null,
1895
        $photoSize = null,
1896
        $photoWidth = null,
1897
        $photoHeight = null,
1898
        $needName = false,
1899
        $needPhoneNumber = false,
1900
        $needEmail = false,
1901
        $needShippingAddress = false,
1902
        $replyToMessageId = null,
1903
        $replyMarkup = null,
1904
        $disableNotification = false,
1905
        $providerData = null,
1906
        $sendPhoneNumberToProvider = false,
1907
        $sendEmailToProvider = false,
1908
        $messageThreadId = null,
1909
        $protectContent = null,
1910
        $allowSendingWithoutReply = null
1911
    ) {
1912
        return Message::fromResponse($this->call('sendInvoice', [
1913
            'chat_id' => $chatId,
1914
            'title' => $title,
1915
            'description' => $description,
1916
            'payload' => $payload,
1917
            'provider_token' => $providerToken,
1918
            'start_parameter' => $startParameter,
1919
            'currency' => $currency,
1920
            'prices' => json_encode($prices),
1921
            'is_flexible' => $isFlexible,
1922
            'photo_url' => $photoUrl,
1923
            'photo_size' => $photoSize,
1924
            'photo_width' => $photoWidth,
1925
            'photo_height' => $photoHeight,
1926
            'need_name' => $needName,
1927
            'need_phone_number' => $needPhoneNumber,
1928
            'need_email' => $needEmail,
1929
            'need_shipping_address' => $needShippingAddress,
1930
            'message_thread_id' => $messageThreadId,
1931
            'reply_to_message_id' => $replyToMessageId,
1932
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1933
            'disable_notification' => (bool) $disableNotification,
1934
            'provider_data' => $providerData,
1935
            'send_phone_number_to_provider' => (bool) $sendPhoneNumberToProvider,
1936
            'send_email_to_provider' => (bool) $sendEmailToProvider,
1937
            'protect_content' => (bool) $protectContent,
1938
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
1939
        ]));
1940
    }
1941
1942
    /**
1943
     * If you sent an invoice requesting a shipping address and the parameter is_flexible was specified, the Bot API
1944
     * will send an Update with a shipping_query field to the bot. Use this method to reply to shipping queries.
1945
     * On success, True is returned.
1946
     *
1947
     * @param string $shippingQueryId
1948
     * @param bool $ok
1949
     * @param array $shippingOptions
1950
     * @param null|string $errorMessage
1951
     *
1952
     * @return bool
1953
     * @throws Exception
1954
     */
1955
    public function answerShippingQuery($shippingQueryId, $ok = true, $shippingOptions = [], $errorMessage = null)
1956
    {
1957
        return $this->call('answerShippingQuery', [
1958
            'shipping_query_id' => $shippingQueryId,
1959
            'ok' => (bool) $ok,
1960
            'shipping_options' => json_encode($shippingOptions),
1961
            'error_message' => $errorMessage
1962
        ]);
1963
    }
1964
1965
    /**
1966
     * Use this method to respond to such pre-checkout queries. On success, True is returned.
1967
     * Note: The Bot API must receive an answer within 10 seconds after the pre-checkout query was sent.
1968
     *
1969
     * @param string $preCheckoutQueryId
1970
     * @param bool $ok
1971
     * @param null|string $errorMessage
1972
     *
1973
     * @return bool
1974
     * @throws Exception
1975
     */
1976
    public function answerPreCheckoutQuery($preCheckoutQueryId, $ok = true, $errorMessage = null)
1977
    {
1978
        return $this->call('answerPreCheckoutQuery', [
1979
            'pre_checkout_query_id' => $preCheckoutQueryId,
1980
            'ok' => (bool) $ok,
1981
            'error_message' => $errorMessage
1982
        ]);
1983
    }
1984
1985
    /**
1986
     * Use this method to restrict a user in a supergroup.
1987
     * The bot must be an administrator in the supergroup for this to work and must have the appropriate admin rights.
1988
     * Pass True for all boolean parameters to lift restrictions from a user.
1989
     *
1990
     * @param string|int $chatId Unique identifier for the target chat or username of the target supergroup
1991
     *                           (in the format @supergroupusername)
1992
     * @param int $userId Unique identifier of the target user
1993
     * @param null|integer $untilDate Date when restrictions will be lifted for the user, unix time.
1994
     *                                If user is restricted for more than 366 days or less than 30 seconds from the current time,
1995
     *                                they are considered to be restricted forever
1996
     * @param bool $canSendMessages Pass True, if the user can send text messages, contacts, locations and venues
1997
     * @param bool $canSendMediaMessages No Pass True, if the user can send audios, documents, photos, videos,
1998
     *                                   video notes and voice notes, implies can_send_messages
1999
     * @param bool $canSendOtherMessages Pass True, if the user can send animations, games, stickers and
2000
     *                                   use inline bots, implies can_send_media_messages
2001
     * @param bool $canAddWebPagePreviews Pass True, if the user may add web page previews to their messages,
2002
     *                                    implies can_send_media_messages
2003
     *
2004
     * @return bool
2005
     * @throws Exception
2006
     */
2007
    public function restrictChatMember(
2008
        $chatId,
2009
        $userId,
2010
        $untilDate = null,
2011
        $canSendMessages = false,
2012
        $canSendMediaMessages = false,
2013
        $canSendOtherMessages = false,
2014
        $canAddWebPagePreviews = false
2015
    ) {
2016
        return $this->call('restrictChatMember', [
2017
            'chat_id' => $chatId,
2018
            'user_id' => $userId,
2019
            'until_date' => $untilDate,
2020
            'can_send_messages' => $canSendMessages,
2021
            'can_send_media_messages' => $canSendMediaMessages,
2022
            'can_send_other_messages' => $canSendOtherMessages,
2023
            'can_add_web_page_previews' => $canAddWebPagePreviews
2024
        ]);
2025
    }
2026
2027
    /**
2028
     * Use this method to promote or demote a user in a supergroup or a channel.
2029
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2030
     * Pass False for all boolean parameters to demote a user.
2031
     *
2032
     * @param string|int $chatId Unique identifier for the target chat or username of the target supergroup
2033
     *                           (in the format @supergroupusername)
2034
     * @param int $userId Unique identifier of the target user
2035
     * @param bool $canChangeInfo Pass True, if the administrator can change chat title, photo and other settings
2036
     * @param bool $canPostMessages Pass True, if the administrator can create channel posts, channels only
2037
     * @param bool $canEditMessages Pass True, if the administrator can edit messages of other users, channels only
2038
     * @param bool $canDeleteMessages Pass True, if the administrator can delete messages of other users
2039
     * @param bool $canInviteUsers Pass True, if the administrator can invite new users to the chat
2040
     * @param bool $canRestrictMembers Pass True, if the administrator can restrict, ban or unban chat members
2041
     * @param bool $canPinMessages Pass True, if the administrator can pin messages, supergroups only
2042
     * @param bool $canPromoteMembers Pass True, if the administrator can add new administrators with a subset of his
2043
     *                                own privileges or demote administrators that he has promoted,directly or
2044
     *                                indirectly (promoted by administrators that were appointed by him)
2045
     * @param bool $canManageTopics Pass True if the user is allowed to create, rename, close, and reopen forum topics, supergroups only
2046
     * @param bool $isAnonymous Pass True if the administrator's presence in the chat is hidden
2047
     * @return bool
2048
     *
2049
     * @throws Exception
2050
     * @throws HttpException
2051
     * @throws InvalidJsonException
2052
     */
2053
    public function promoteChatMember(
2054
        $chatId,
2055
        $userId,
2056
        $canChangeInfo = true,
2057
        $canPostMessages = true,
2058
        $canEditMessages = true,
2059
        $canDeleteMessages = true,
2060
        $canInviteUsers = true,
2061
        $canRestrictMembers = true,
2062
        $canPinMessages = true,
2063
        $canPromoteMembers = true,
2064
        $canManageTopics = true,
2065
        $isAnonymous = false
2066
    ) {
2067
        return $this->call('promoteChatMember', [
2068
            'chat_id' => $chatId,
2069
            'user_id' => $userId,
2070
            'is_anonymous' => $isAnonymous,
2071
            'can_change_info' => $canChangeInfo,
2072
            'can_post_messages' => $canPostMessages,
2073
            'can_edit_messages' => $canEditMessages,
2074
            'can_delete_messages' => $canDeleteMessages,
2075
            'can_invite_users' => $canInviteUsers,
2076
            'can_restrict_members' => $canRestrictMembers,
2077
            'can_pin_messages' => $canPinMessages,
2078
            'can_promote_members' => $canPromoteMembers,
2079
            'can_manage_topics' => $canManageTopics
2080
        ]);
2081
    }
2082
2083
    /**
2084
     * Use this method to export an invite link to a supergroup or a channel.
2085
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2086
     *
2087
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2088
     *                           (in the format @channelusername)
2089
     * @return string
2090
     * @throws Exception
2091
     */
2092
    public function exportChatInviteLink($chatId)
2093
    {
2094
        return $this->call('exportChatInviteLink', [
2095
            'chat_id' => $chatId
2096
        ]);
2097
    }
2098
2099
    /**
2100
     * Use this method to set a new profile photo for the chat. Photos can't be changed for private chats.
2101
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2102
     *
2103
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2104
     *                           (in the format @channelusername)
2105
     * @param \CURLFile|string $photo New chat photo, uploaded using multipart/form-data
2106
     *
2107
     * @return bool
2108
     * @throws Exception
2109
     */
2110
    public function setChatPhoto($chatId, $photo)
2111
    {
2112
        return $this->call('setChatPhoto', [
2113
            'chat_id' => $chatId,
2114
            'photo' => $photo
2115
        ]);
2116
    }
2117
2118
    /**
2119
     * Use this method to delete a chat photo. Photos can't be changed for private chats.
2120
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2121
     *
2122
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2123
     *                           (in the format @channelusername)
2124
     *
2125
     * @return bool
2126
     * @throws Exception
2127
     */
2128
    public function deleteChatPhoto($chatId)
2129
    {
2130
        return $this->call('deleteChatPhoto', [
2131
            'chat_id' => $chatId
2132
        ]);
2133
    }
2134
2135
    /**
2136
     * Use this method to change the title of a chat. Titles can't be changed for private chats.
2137
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2138
     *
2139
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2140
     *                           (in the format @channelusername)
2141
     * @param string $title New chat title, 1-255 characters
2142
     *
2143
     * @return bool
2144
     * @throws Exception
2145
     */
2146
    public function setChatTitle($chatId, $title)
2147
    {
2148
        return $this->call('setChatTitle', [
2149
            'chat_id' => $chatId,
2150
            'title' => $title
2151
        ]);
2152
    }
2153
2154
    /**
2155
     * Use this method to change the description of a supergroup or a channel.
2156
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2157
     *
2158
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2159
     *                           (in the format @channelusername)
2160
     * @param string|null $description New chat description, 0-255 characters
2161
     *
2162
     * @return bool
2163
     * @throws Exception
2164
     */
2165
    public function setChatDescription($chatId, $description = null)
2166
    {
2167
        return $this->call('setChatDescription', [
2168
            'chat_id' => $chatId,
2169
            'title' => $description
2170
        ]);
2171
    }
2172
2173
    /**
2174
     * Use this method to pin a message in a supergroup.
2175
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2176
     *
2177
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2178
     *                           (in the format @channelusername)
2179
     * @param int $messageId Identifier of a message to pin
2180
     * @param bool $disableNotification
2181
     *
2182
     * @return bool
2183
     * @throws Exception
2184
     */
2185
    public function pinChatMessage($chatId, $messageId, $disableNotification = false)
2186
    {
2187
        return $this->call('pinChatMessage', [
2188
            'chat_id' => $chatId,
2189
            'message_id' => $messageId,
2190
            'disable_notification' => $disableNotification
2191
        ]);
2192
    }
2193
2194
    /**
2195
     * Use this method to unpin a message in a supergroup chat.
2196
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
2197
     *
2198
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2199
     *                           (in the format @channelusername)
2200
     *
2201
     * @return bool
2202
     * @throws Exception
2203
     */
2204
    public function unpinChatMessage($chatId)
2205
    {
2206
        return $this->call('unpinChatMessage', [
2207
            'chat_id' => $chatId
2208
        ]);
2209
    }
2210
2211
    /**
2212
     * Use this method to get up to date information about the chat
2213
     * (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.).
2214
     *
2215
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2216
     *                           (in the format @channelusername)
2217
     *
2218
     * @return Chat
2219
     * @throws Exception
2220
     */
2221
    public function getChat($chatId)
2222
    {
2223
        return Chat::fromResponse($this->call('getChat', [
2224
            'chat_id' => $chatId
2225
        ]));
2226
    }
2227
2228
    /**
2229
     * Use this method to get information about a member of a chat.
2230
     *
2231
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2232
     *                           (in the format @channelusername)
2233
     * @param int $userId
2234
     *
2235
     * @return ChatMember
2236
     * @throws Exception
2237
     */
2238
    public function getChatMember($chatId, $userId)
2239
    {
2240
        return ChatMember::fromResponse($this->call('getChatMember', [
2241
            'chat_id' => $chatId,
2242
            'user_id' => $userId
2243
        ]));
2244
    }
2245
2246
    /**
2247
     * Use this method for your bot to leave a group, supergroup or channel.
2248
     *
2249
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2250
     *                           (in the format @channelusername)
2251
     *
2252
     * @return bool
2253
     * @throws Exception
2254
     */
2255
    public function leaveChat($chatId)
2256
    {
2257
        return $this->call('leaveChat', [
2258
            'chat_id' => $chatId
2259
        ]);
2260
    }
2261
2262
    /**
2263
     * Use this method to get the number of members in a chat.
2264
     *
2265
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2266
     *                           (in the format @channelusername)
2267
     *
2268
     * @return int
2269
     * @throws Exception
2270
     */
2271
    public function getChatMembersCount($chatId)
2272
    {
2273
        return $this->call(
2274
            'getChatMembersCount',
2275
            [
2276
                'chat_id' => $chatId
2277
            ]
2278
        );
2279
    }
2280
2281
    /**
2282
     * Use this method to get a list of administrators in a chat.
2283
     *
2284
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2285
     *                           (in the format @channelusername)
2286
     *
2287
     * @return ChatMember[]
2288
     * @throws InvalidArgumentException
2289
     * @throws Exception
2290
     */
2291
    public function getChatAdministrators($chatId)
2292
    {
2293
        return ArrayOfChatMemberEntity::fromResponse(
2294
            $this->call(
2295
                'getChatAdministrators',
2296
                [
2297
                    'chat_id' => $chatId
2298
                ]
2299
            )
2300
        );
2301
    }
2302
2303
    /**
2304
     * As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1 minute long.
2305
     * Use this method to send video messages.
2306
     * On success, the sent Message is returned.
2307
     *
2308
     * @param int|string $chatId chat_id or @channel_name
2309
     * @param \CURLFile|string $videoNote
2310
     * @param int|null $duration
2311
     * @param int|null $length
2312
     * @param int|null $replyToMessageId
2313
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
2314
     * @param bool $disableNotification
2315
     * @param int|null $messageThreadId
2316
     * @param bool|null $protectContent
2317
     * @param bool|null $allowSendingWithoutReply
2318
     * @param \CURLFile|\CURLStringFile|string|null $thumbnail
2319
     *
2320
     * @return Message
2321
     * @throws InvalidArgumentException
2322
     * @throws Exception
2323
     */
2324
    public function sendVideoNote(
2325
        $chatId,
2326
        $videoNote,
2327
        $duration = null,
2328
        $length = null,
2329
        $replyToMessageId = null,
2330
        $replyMarkup = null,
2331
        $disableNotification = false,
2332
        $messageThreadId = null,
2333
        $protectContent = null,
2334
        $allowSendingWithoutReply = null,
2335
        $thumbnail = null
2336
    ) {
2337
        return Message::fromResponse($this->call('sendVideoNote', [
2338
            'chat_id' => $chatId,
2339
            'video_note' => $videoNote,
2340
            'duration' => $duration,
2341
            'length' => $length,
2342
            'message_thread_id' => $messageThreadId,
2343
            'reply_to_message_id' => $replyToMessageId,
2344
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
2345
            'disable_notification' => (bool) $disableNotification,
2346
            'protect_content' => (bool) $protectContent,
2347
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
2348
            'thumbnail' => $thumbnail,
2349
        ]));
2350
    }
2351
2352
    /**
2353
     * Use this method to send a group of photos or videos as an album.
2354
     * On success, the sent \TelegramBot\Api\Types\Message is returned.
2355
     *
2356
     * @param int|string $chatId
2357
     * @param ArrayOfInputMedia $media
2358
     * @param bool $disableNotification
2359
     * @param int|null $replyToMessageId
2360
     * @param int|null $messageThreadId
2361
     * @param bool|null $protectContent
2362
     * @param bool|null $allowSendingWithoutReply
2363
     * @param array<string, \CURLFile|\CURLStringFile> $attachments Attachments to use in attach://<attachment>
2364
     *
2365
     * @return Message[]
2366
     * @throws Exception
2367
     */
2368
    public function sendMediaGroup(
2369
        $chatId,
2370
        $media,
2371
        $disableNotification = false,
2372
        $replyToMessageId = null,
2373
        $messageThreadId = null,
2374
        $protectContent = null,
2375
        $allowSendingWithoutReply = null,
2376
        $attachments = []
2377
    ) {
2378
        return ArrayOfMessages::fromResponse($this->call('sendMediaGroup', [
2379
            'chat_id' => $chatId,
2380
            'media' => $media->toJson(),
2381
            'message_thread_id' => $messageThreadId,
2382
            'reply_to_message_id' => (int) $replyToMessageId,
2383
            'disable_notification' => (bool) $disableNotification,
2384
            'protect_content' => (bool) $protectContent,
2385
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
2386
        ] + $attachments));
2387
    }
2388
2389
    /**
2390
     * Enable proxy for curl requests. Empty string will disable proxy.
2391
     *
2392
     * @param string $proxyString
2393
     * @param bool $socks5
2394
     *
2395
     * @return BotApi
2396
     */
2397
    public function setProxy($proxyString = '', $socks5 = false)
2398
    {
2399
        if (empty($proxyString)) {
2400
            $this->proxySettings = [];
2401
            return $this;
2402
        }
2403
2404
        $this->proxySettings = [
2405
            CURLOPT_PROXY => $proxyString,
2406
            CURLOPT_HTTPPROXYTUNNEL => true,
2407
        ];
2408
2409
        if ($socks5) {
2410
            $this->proxySettings[CURLOPT_PROXYTYPE] = CURLPROXY_SOCKS5;
2411
        }
2412
        return $this;
2413
    }
2414
2415
    /**
2416
     * Use this method to send a native poll. A native poll can't be sent to a private chat.
2417
     * On success, the sent \TelegramBot\Api\Types\Message is returned.
2418
     *
2419
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2420
     *                           (in the format @channelusername)
2421
     * @param string $question Poll question, 1-255 characters
2422
     * @param array $options A JSON-serialized list of answer options, 2-10 strings 1-100 characters each
2423
     * @param bool $isAnonymous True, if the poll needs to be anonymous, defaults to True
2424
     * @param string|null $type Poll type, “quiz” or “regular”, defaults to “regular”
2425
     * @param bool $allowsMultipleAnswers True, if the poll allows multiple answers,
2426
     *                                    ignored for polls in quiz mode, defaults to False
2427
     * @param string|null $correctOptionId 0-based identifier of the correct answer option, required for polls in quiz mode
2428
     * @param bool $isClosed Pass True, if the poll needs to be immediately closed. This can be useful for poll preview.
2429
     * @param bool $disableNotification Sends the message silently. Users will receive a notification with no sound.
2430
     * @param int|null $replyToMessageId If the message is a reply, ID of the original message
2431
     * @param object|null $replyMarkup Additional interface options. A JSON-serialized object for an inline keyboard,
2432
     *                                 custom reply keyboard, instructions to remove reply
2433
     *                                 keyboard or to force a reply from the user.
2434
     * @param int|null $messageThreadId Unique identifier for the target message thread (topic) of the forum; for forum supergroups only
2435
     * @param bool|null $protectContent
2436
     * @param bool|null $allowSendingWithoutReply
2437
     *
2438
     * @return Message
2439
     * @throws Exception
2440
     * @throws HttpException
2441
     * @throws InvalidJsonException
2442
     */
2443
    public function sendPoll(
2444
        $chatId,
2445
        $question,
2446
        $options,
2447
        $isAnonymous = false,
2448
        $type = null,
2449
        $allowsMultipleAnswers = false,
2450
        $correctOptionId = null,
2451
        $isClosed = false,
2452
        $disableNotification = false,
2453
        $replyToMessageId = null,
2454
        $replyMarkup = null,
2455
        $messageThreadId = null,
2456
        $protectContent = null,
2457
        $allowSendingWithoutReply = null
2458
    ) {
2459
        return Message::fromResponse($this->call('sendPoll', [
2460
            'chat_id' => $chatId,
2461
            'question' => $question,
2462
            'options' => json_encode($options),
2463
            'is_anonymous' => (bool) $isAnonymous,
2464
            'type' => (string) $type,
2465
            'allows_multiple_answers' => (bool) $allowsMultipleAnswers,
2466
            'correct_option_id' => (int) $correctOptionId,
2467
            'is_closed' => (bool) $isClosed,
2468
            'disable_notification' => (bool) $disableNotification,
2469
            'message_thread_id' => $messageThreadId,
2470
            'reply_to_message_id' => (int) $replyToMessageId,
2471
            'reply_markup' => $replyMarkup === null ? $replyMarkup : $replyMarkup->toJson(),
2472
            'protect_content' => (bool) $protectContent,
2473
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
2474
        ]));
2475
    }
2476
2477
    /**
2478
     * Use this method to send a dice, which will have a random value from 1 to 6.
2479
     * On success, the sent Message is returned. (Yes, we're aware of the “proper” singular of die.
2480
     * But it's awkward, and we decided to help it change. One dice at a time!)
2481
     *
2482
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
2483
     *                           (in the format @channelusername)
2484
     * @param string $emoji Emoji on which the dice throw animation is based. Currently, must be one of “🎲”,
2485
     *                      “🎯”, “🏀”, “⚽”, or “🎰”. Dice can have values 1-6 for “🎲” and “🎯”, values 1-5 for “🏀” and “⚽”, and
2486
     *                      values 1-64 for “🎰”. Defaults to “🎲
2487
     * @param bool $disableNotification Sends the message silently. Users will receive a notification with no sound.
2488
     * @param string|null $replyToMessageId If the message is a reply, ID of the original message
2489
     * @param bool $allowSendingWithoutReply Pass True, if the message should be sent even if the specified replied-to
2490
     *                                       message is not found,
2491
     * @param object|null $replyMarkup Additional interface options. A JSON-serialized object for an inline keyboard,
2492
     *                                 custom reply keyboard, instructions to remove reply
2493
     *                                 keyboard or to force a reply from the user.
2494
     * @param int|null $messageThreadId
2495
     * @param bool|null $protectContent
2496
     *
2497
     * @return Message
2498
     * @throws Exception
2499
     * @throws HttpException
2500
     * @throws InvalidJsonException
2501
     */
2502
    public function sendDice(
2503
        $chatId,
2504
        $emoji,
2505
        $disableNotification = false,
2506
        $replyToMessageId = null,
2507
        $allowSendingWithoutReply = false,
2508
        $replyMarkup = null,
2509
        $messageThreadId = null,
2510
        $protectContent = null
2511
    ) {
2512
        return Message::fromResponse($this->call('sendDice', [
2513
            'chat_id' => $chatId,
2514
            'emoji' => $emoji,
2515
            'disable_notification' => (bool) $disableNotification,
2516
            'message_thread_id' => $messageThreadId,
2517
            'reply_to_message_id' => (int) $replyToMessageId,
2518
            'allow_sending_without_reply' => (bool) $allowSendingWithoutReply,
2519
            'reply_markup' => $replyMarkup === null ? $replyMarkup : $replyMarkup->toJson(),
2520
            'protect_content' => (bool) $protectContent,
2521
        ]));
2522
    }
2523
2524
    /**
2525
     * Use this method to stop a poll which was sent by the bot.
2526
     * On success, the stopped \TelegramBot\Api\Types\Poll with the final results is returned.
2527
     *
2528
     * @param int|string $chatId
2529
     * @param int $messageId
2530
     * @param ReplyKeyboardMarkup|ReplyKeyboardHide|ForceReply|ReplyKeyboardRemove|null $replyMarkup
2531
     * @return Poll
2532
     * @throws InvalidArgumentException
2533
     * @throws Exception
2534
     */
2535
    public function stopPoll(
2536
        $chatId,
2537
        $messageId,
2538
        $replyMarkup = null
2539
    ) {
2540
        return Poll::fromResponse($this->call('stopPoll', [
2541
            'chat_id' => $chatId,
2542
            'message_id' => $messageId,
2543
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
2544
        ]));
2545
    }
2546
2547
    /**
2548
     * Use this method to create a topic in a forum supergroup chat.
2549
     * The bot must be an administrator in the chat for this to work
2550
     * and must have the can_manage_topics administrator rights.
2551
     * Returns information about the created topic as a ForumTopic object.
2552
     *
2553
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2554
     * @param string $name Topic name, 1-128 characters
2555
     * @param int $iconColor Color of the topic icon in RGB format.
2556
     *                       Currently, must be one of 7322096 (0x6FB9F0), 16766590 (0xFFD67E), 13338331 (0xCB86DB),
2557
     *                       9367192 (0x8EEE98), 16749490 (0xFF93B2), or 16478047 (0xFB6F5F)
2558
     * @param int|null $iconCustomEmojiId Unique identifier of the custom emoji shown as the topic icon.
2559
     *                                    Use getForumTopicIconStickers to get all allowed custom emoji identifiers.
2560
     *
2561
     * @return ForumTopic
2562
     *
2563
     * @throws Exception
2564
     *
2565
     * @author bernard-ng <[email protected]>
2566
     */
2567
    public function createForumTopic(
2568
        $chatId,
2569
        $name,
2570
        $iconColor,
2571
        $iconCustomEmojiId = null
2572
    ) {
2573
        return ForumTopic::fromResponse($this->call('createForumTopic', [
2574
            'chat_id' => $chatId,
2575
            'name' => $name,
2576
            'icon_color' => $iconColor,
2577
            'icon_custom_emoji_id' => $iconCustomEmojiId,
2578
        ]));
2579
    }
2580
2581
    /**
2582
     * Use this method to edit name and icon of a topic in a forum supergroup chat.
2583
     * The bot must be an administrator in the chat for this to work and must have can_manage_topics administrator rights,
2584
     * unless it is the creator of the topic. Returns True on success.
2585
     *
2586
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2587
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2588
     * @param string $name Topic name, 1-128 characters
2589
     * @param int|null $iconCustomEmojiId Unique identifier of the custom emoji shown as the topic icon.
2590
     *                                    Use getForumTopicIconStickers to get all allowed custom emoji identifiers.
2591
     *
2592
     * @return bool
2593
     * @throws Exception
2594
     *
2595
     * @author bernard-ng <[email protected]>
2596
     */
2597
    public function editForumTopic(
2598
        $chatId,
2599
        $messageThreadId,
2600
        $name,
2601
        $iconCustomEmojiId = null
2602
    ) {
2603
        return $this->call('editForumTopic', [
2604
            'chat_id' => $chatId,
2605
            'message_thread_id' => $messageThreadId,
2606
            'name' => $name,
2607
            'icon_custom_emoji_id' => $iconCustomEmojiId,
2608
        ]);
2609
    }
2610
2611
    /**
2612
     * Use this method to delete a topic in a forum supergroup chat.
2613
     * The bot must be an administrator in the chat for this to work and must have can_manage_topics administrator rights,
2614
     * unless it is the creator of the topic. Returns True on success.
2615
     *
2616
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2617
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2618
     *
2619
     * @return bool
2620
     * @throws Exception
2621
     *
2622
     * @author bernard-ng <[email protected]>
2623
     */
2624
    public function closeForumTopic($chatId, $messageThreadId)
2625
    {
2626
        return $this->call('closeForumTopic', [
2627
            'chat_id' => $chatId,
2628
            'message_thread_id' => $messageThreadId,
2629
        ]);
2630
    }
2631
2632
    /**
2633
     * Use this method to reopen a closed topic in a forum supergroup chat.
2634
     * The bot must be an administrator in the chat for this to work and must have the can_manage_topics administrator rights,
2635
     * unless it is the creator of the topic. Returns True on success.
2636
     *
2637
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2638
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2639
     *
2640
     * @return bool
2641
     * @throws Exception
2642
     *
2643
     * @author bernard-ng <[email protected]>
2644
     */
2645
    public function reopenForumTopic($chatId, $messageThreadId)
2646
    {
2647
        return $this->call('reopenForumTopic', [
2648
            'chat_id' => $chatId,
2649
            'message_thread_id' => $messageThreadId,
2650
        ]);
2651
    }
2652
2653
    /**
2654
     * Use this method to delete a forum topic along with all its messages in a forum supergroup chat.
2655
     * The bot must be an administrator in the chat for this to work and must have the can_delete_messages administrator rights.
2656
     * Returns True on success.
2657
     *
2658
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2659
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2660
     *
2661
     * @return bool
2662
     * @throws Exception
2663
     *
2664
     * @author bernard-ng <[email protected]>
2665
     */
2666
    public function deleteForumTopic($chatId, $messageThreadId)
2667
    {
2668
        return $this->call('deleteForumTopic', [
2669
            'chat_id' => $chatId,
2670
            'message_thread_id' => $messageThreadId,
2671
        ]);
2672
    }
2673
2674
    /**
2675
     * Use this method to clear the list of pinned messages in a forum topic.
2676
     * 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.
2677
     * Returns True on success.
2678
     *
2679
     * @param int|string $chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
2680
     * @param int $messageThreadId Unique identifier for the target message thread of the forum topic
2681
     *
2682
     * @return bool
2683
     * @throws Exception
2684
     *
2685
     * @author bernard-ng <[email protected]>
2686
     */
2687
    public function unpinAllForumTopicMessages($chatId, $messageThreadId)
2688
    {
2689
        return $this->call('unpinAllForumTopicMessages', [
2690
            'chat_id' => $chatId,
2691
            'message_thread_id' => $messageThreadId,
2692
        ]);
2693
    }
2694
2695
    /**
2696
     * Use this method to get custom emoji stickers, which can be used as a forum topic icon by any user.
2697
     * Requires no parameters. Returns an Array of Sticker objects.
2698
     *
2699
     * @return Sticker[]
2700
     * @throws Exception
2701
     *
2702
     * @author bernard-ng <[email protected]>
2703
     */
2704
    public function getForumTopicIconStickers()
2705
    {
2706
        return ArrayOfSticker::fromResponse($this->call('getForumTopicIconStickers'));
2707
    }
2708
2709
    /**
2710
     * @param string $webAppQueryId
2711
     * @param AbstractInlineQueryResult $result
2712
     * @return SentWebAppMessage
2713
     * @throws Exception
2714
     * @throws HttpException
2715
     * @throws InvalidArgumentException
2716
     * @throws InvalidJsonException
2717
     */
2718
    public function answerWebAppQuery($webAppQueryId, $result)
2719
    {
2720
        return SentWebAppMessage::fromResponse($this->call('answerWebAppQuery', [
2721
            'web_app_query_id' => $webAppQueryId,
2722
            'result' => $result->toJson(),
2723
        ]));
2724
    }
2725
2726
    /**
2727
     * Set an option for a cURL transfer
2728
     *
2729
     * @param int $option The CURLOPT_XXX option to set
2730
     * @param mixed $value The value to be set on option
2731
     *
2732
     * @return void
2733
     */
2734
    public function setCurlOption($option, $value)
2735
    {
2736
        $this->customCurlOptions[$option] = $value;
2737
    }
2738
2739
    /**
2740
     * Unset an option for a cURL transfer
2741
     *
2742
     * @param int $option The CURLOPT_XXX option to unset
2743
     *
2744
     * @return void
2745
     */
2746
    public function unsetCurlOption($option)
2747
    {
2748
        unset($this->customCurlOptions[$option]);
2749
    }
2750
2751
    /**
2752
     * Clean custom options
2753
     *
2754
     * @return void
2755
     */
2756
    public function resetCurlOptions()
2757
    {
2758
        $this->customCurlOptions = [];
2759
    }
2760
}
2761