Passed
Pull Request — master (#449)
by Alexander
02:30
created

BotApi::createChatInviteLink()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

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

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

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

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

filter:
    dependency_paths: ["lib/*"]

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

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