Completed
Push — master ( be22ff...83e3a1 )
by Alexander
20s queued 15s
created

BotApi::answerWebAppQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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