Passed
Pull Request — master (#420)
by Alexander
01:53
created

BotApi::sendContact()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 9
c 1
b 0
f 1
dl 0
loc 19
ccs 0
cts 6
cp 0
rs 9.9666
cc 2
nc 1
nop 8
crap 6

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

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

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

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