Passed
Pull Request — master (#227)
by
unknown
02:55
created

BotApi::sendAudio()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 23

Duplication

Lines 23
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 23
loc 23
ccs 0
cts 0
cp 0
rs 9.552
c 0
b 0
f 0
cc 2
nc 1
nop 9
crap 6

How to fix   Many Parameters   

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace TelegramBot\Api;
4
5
use TelegramBot\Api\Types\ArrayOfChatMemberEntity;
6
use TelegramBot\Api\Types\ArrayOfMessages;
7
use TelegramBot\Api\Types\ArrayOfUpdates;
8
use TelegramBot\Api\Types\Chat;
9
use TelegramBot\Api\Types\ChatMember;
10
use TelegramBot\Api\Types\File;
11
use TelegramBot\Api\Types\Inline\QueryResult\AbstractInlineQueryResult;
12
use TelegramBot\Api\Types\InputMedia\ArrayOfInputMedia;
13
use TelegramBot\Api\Types\Message;
14
use TelegramBot\Api\Types\Poll;
15
use TelegramBot\Api\Types\Update;
16
use TelegramBot\Api\Types\User;
17
use TelegramBot\Api\Types\UserProfilePhotos;
18
19
/**
20
 * Class BotApi
21
 *
22
 * @package TelegramBot\Api
23
 */
24
class BotApi
25
{
26
    /**
27
     * HTTP codes
28
     *
29
     * @var array
30
     */
31
    public static $codes = [
32
        // Informational 1xx
33
        100 => 'Continue',
34
        101 => 'Switching Protocols',
35
        102 => 'Processing',            // RFC2518
36
        // Success 2xx
37
        200 => 'OK',
38
        201 => 'Created',
39
        202 => 'Accepted',
40
        203 => 'Non-Authoritative Information',
41
        204 => 'No Content',
42
        205 => 'Reset Content',
43
        206 => 'Partial Content',
44
        207 => 'Multi-Status',          // RFC4918
45
        208 => 'Already Reported',      // RFC5842
46
        226 => 'IM Used',               // RFC3229
47
        // Redirection 3xx
48
        300 => 'Multiple Choices',
49
        301 => 'Moved Permanently',
50
        302 => 'Found', // 1.1
51
        303 => 'See Other',
52
        304 => 'Not Modified',
53
        305 => 'Use Proxy',
54
        // 306 is deprecated but reserved
55
        307 => 'Temporary Redirect',
56
        308 => 'Permanent Redirect',    // RFC7238
57
        // Client Error 4xx
58
        400 => 'Bad Request',
59
        401 => 'Unauthorized',
60
        402 => 'Payment Required',
61
        403 => 'Forbidden',
62
        404 => 'Not Found',
63
        405 => 'Method Not Allowed',
64
        406 => 'Not Acceptable',
65
        407 => 'Proxy Authentication Required',
66
        408 => 'Request Timeout',
67
        409 => 'Conflict',
68
        410 => 'Gone',
69
        411 => 'Length Required',
70
        412 => 'Precondition Failed',
71
        413 => 'Payload Too Large',
72
        414 => 'URI Too Long',
73
        415 => 'Unsupported Media Type',
74
        416 => 'Range Not Satisfiable',
75
        417 => 'Expectation Failed',
76
        422 => 'Unprocessable Entity',                                        // RFC4918
77
        423 => 'Locked',                                                      // RFC4918
78
        424 => 'Failed Dependency',                                           // RFC4918
79
        425 => 'Reserved for WebDAV advanced collections expired proposal',   // RFC2817
80
        426 => 'Upgrade Required',                                            // RFC2817
81
        428 => 'Precondition Required',                                       // RFC6585
82
        429 => 'Too Many Requests',                                           // RFC6585
83
        431 => 'Request Header Fields Too Large',                             // RFC6585
84
        // Server Error 5xx
85
        500 => 'Internal Server Error',
86
        501 => 'Not Implemented',
87
        502 => 'Bad Gateway',
88
        503 => 'Service Unavailable',
89
        504 => 'Gateway Timeout',
90
        505 => 'HTTP Version Not Supported',
91
        506 => 'Variant Also Negotiates (Experimental)',                      // RFC2295
92
        507 => 'Insufficient Storage',                                        // RFC4918
93
        508 => 'Loop Detected',                                               // RFC5842
94
        510 => 'Not Extended',                                                // RFC2774
95
        511 => 'Network Authentication Required',                             // RFC6585
96
    ];
97
98
    private $proxySettings = [];
99
100
    /**
101
     * Default http status code
102
     */
103
    const DEFAULT_STATUS_CODE = 200;
104
105
    /**
106
     * Not Modified http status code
107
     */
108
    const NOT_MODIFIED_STATUS_CODE = 304;
109
110
    /**
111
     * Limits for tracked ids
112
     */
113
    const MAX_TRACKED_EVENTS = 200;
114
115
    /**
116
     * Url prefixes
117
     */
118
    const URL_PREFIX = 'https://api.telegram.org/bot';
119
120
    /**
121
     * Url prefix for files
122
     */
123
    const FILE_URL_PREFIX = 'https://api.telegram.org/file/bot';
124
125
    /**
126
     * CURL object
127
     *
128
     * @var
129
     */
130
    protected $curl;
131
132
    /**
133
     * CURL custom options
134
     *
135
     * @var array
136
     */
137
    protected $customCurlOptions = [];
138
139
    /**
140
     * Bot token
141
     *
142
     * @var string
143
     */
144
    protected $token;
145
146
    /**
147
     * Botan tracker
148
     *
149
     * @var \TelegramBot\Api\Botan
150
     */
151
    protected $tracker;
152
153
    /**
154
     * list of event ids
155
     *
156
     * @var array
157
     */
158
    protected $trackedEvents = [];
159
160
    /**
161
     * Check whether return associative array
162
     *
163
     * @var bool
164
     */
165
    protected $returnArray = true;
166
167
    /**
168
     * Constructor
169
     *
170
     * @param string $token Telegram Bot API token
171
     * @param string|null $trackerToken Yandex AppMetrica application api_key
172
     */
173 9
    public function __construct($token, $trackerToken = null)
174
    {
175 9
        $this->curl = curl_init();
176 9
        $this->token = $token;
177
178 9
        if ($trackerToken) {
179
            $this->tracker = new Botan($trackerToken);
180
        }
181 9
    }
182
183
    /**
184
     * Set return array
185
     *
186
     * @param bool $mode
187
     *
188
     * @return $this
189
     */
190
    public function setModeObject($mode = true)
191
    {
192
        $this->returnArray = !$mode;
193
194
        return $this;
195
    }
196
197
198
    /**
199
     * Call method
200
     *
201
     * @param string $method
202
     * @param array|null $data
203
     *
204
     * @return mixed
205
     * @throws \TelegramBot\Api\Exception
206
     * @throws \TelegramBot\Api\HttpException
207
     * @throws \TelegramBot\Api\InvalidJsonException
208
     */
209
    public function call($method, array $data = null)
210
    {
211
        $options = $this->proxySettings + [
212
            CURLOPT_URL => $this->getUrl().'/'.$method,
213
            CURLOPT_RETURNTRANSFER => true,
214
            CURLOPT_POST => null,
215
            CURLOPT_POSTFIELDS => null,
216
            CURLOPT_TIMEOUT => 5,
217
        ];
218
219
        if ($data) {
220
            $options[CURLOPT_POST] = true;
221
            $options[CURLOPT_POSTFIELDS] = $data;
222
        }
223
224
        if (!empty($this->customCurlOptions) && is_array($this->customCurlOptions)) {
225
            $options = $this->customCurlOptions + $options;
226
        }
227
228
        $response = self::jsonValidate($this->executeCurl($options), $this->returnArray);
229
230
        if ($this->returnArray) {
231
            if (!isset($response['ok'])) {
232
                throw new Exception($response['description'], $response['error_code']);
233
            }
234
235
            return $response['result'];
236
        }
237
238
        if (!$response->ok) {
239
            throw new Exception($response->description, $response->error_code);
240
        }
241
242
        return $response->result;
243
    }
244
245
    /**
246
     * curl_exec wrapper for response validation
247
     *
248
     * @param array $options
249
     *
250
     * @return string
251
     *
252
     * @throws \TelegramBot\Api\HttpException
253
     */
254
    protected function executeCurl(array $options)
255
    {
256
        curl_setopt_array($this->curl, $options);
257
258
        $result = curl_exec($this->curl);
259
        self::curlValidate($this->curl, $result);
260
        if ($result === false) {
261
            throw new HttpException(curl_error($this->curl), curl_errno($this->curl));
262
        }
263
264
        return $result;
265
    }
266
267
    /**
268
     * Response validation
269
     *
270
     * @param resource $curl
271
     * @param string $response
272
     * @throws HttpException
273
     */
274
    public static function curlValidate($curl, $response = null)
275
    {
276
        $json = json_decode($response, true)?: [];
277
        if (($httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE))
278
            && !in_array($httpCode, [self::DEFAULT_STATUS_CODE, self::NOT_MODIFIED_STATUS_CODE])
279
        ) {
280
            $errorDescription = array_key_exists('description', $json) ? $json['description'] : self::$codes[$httpCode];
281
            $errorParameters = array_key_exists('parameters', $json) ? $json['parameters'] : [];
282
            throw new HttpException($errorDescription, $httpCode, null, $errorParameters);
283
        }
284
    }
285
286
    /**
287
     * JSON validation
288
     *
289
     * @param string $jsonString
290
     * @param boolean $asArray
291
     *
292
     * @return object|array
293
     * @throws \TelegramBot\Api\InvalidJsonException
294
     */
295
    public static function jsonValidate($jsonString, $asArray)
296
    {
297
        $json = json_decode($jsonString, $asArray);
298
299
        if (json_last_error() != JSON_ERROR_NONE) {
300
            throw new InvalidJsonException(json_last_error_msg(), json_last_error());
301
        }
302
303
        return $json;
304
    }
305
306
    /**
307
     * Use this method to send text messages. On success, the sent \TelegramBot\Api\Types\Message is returned.
308
     *
309
     * @param int|string $chatId
310
     * @param string $text
311
     * @param string|null $parseMode
312
     * @param bool $disablePreview
313
     * @param int|null $replyToMessageId
314
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
315
     *        Types\ReplyKeyboardRemove|null $replyMarkup
316
     * @param bool $disableNotification
317
     *
318
     * @return \TelegramBot\Api\Types\Message
319
     * @throws \TelegramBot\Api\InvalidArgumentException
320
     * @throws \TelegramBot\Api\Exception
321
     */
322
    public function sendMessage(
323
        $chatId,
324
        $text,
325
        $parseMode = null,
326
        $disablePreview = false,
327
        $replyToMessageId = null,
328
        $replyMarkup = null,
329
        $disableNotification = false
330
    ) {
331
        return Message::fromResponse($this->call('sendMessage', [
332
            'chat_id' => $chatId,
333
            'text' => $text,
334
            'parse_mode' => $parseMode,
335
            'disable_web_page_preview' => $disablePreview,
336
            'reply_to_message_id' => (int)$replyToMessageId,
337
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
338
            'disable_notification' => (bool)$disableNotification,
339
        ]));
340
    }
341
342
    /**
343
     * Use this method to send phone contacts
344
     *
345
     * @param int|string $chatId chat_id or @channel_name
346
     * @param string $phoneNumber
347
     * @param string $firstName
348
     * @param string $lastName
349
     * @param int|null $replyToMessageId
350
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
351
     *        Types\ReplyKeyboardRemove|null $replyMarkup
352
     * @param bool $disableNotification
353
     *
354
     * @return \TelegramBot\Api\Types\Message
355
     * @throws \TelegramBot\Api\Exception
356
     */
357
    public function sendContact(
358
        $chatId,
359
        $phoneNumber,
360
        $firstName,
361
        $lastName = null,
362
        $replyToMessageId = null,
363
        $replyMarkup = null,
364
        $disableNotification = false
365
    ) {
366
        return Message::fromResponse($this->call('sendContact', [
367
            'chat_id' => $chatId,
368
            'phone_number' => $phoneNumber,
369
            'first_name' => $firstName,
370
            'last_name' => $lastName,
371
            'reply_to_message_id' => $replyToMessageId,
372
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
373
            'disable_notification' => (bool)$disableNotification,
374
        ]));
375
    }
376
377
    /**
378
     * Use this method when you need to tell the user that something is happening on the bot's side.
379
     * The status is set for 5 seconds or less (when a message arrives from your bot,
380
     * Telegram clients clear its typing status).
381
     *
382
     * We only recommend using this method when a response from the bot will take a noticeable amount of time to arrive.
383
     *
384
     * Type of action to broadcast. Choose one, depending on what the user is about to receive:
385
     * `typing` for text messages, `upload_photo` for photos, `record_video` or `upload_video` for videos,
386
     * `record_audio` or upload_audio for audio files, `upload_document` for general files,
387
     * `find_location` for location data.
388
     *
389
     * @param int $chatId
390
     * @param string $action
391
     *
392
     * @return bool
393
     * @throws \TelegramBot\Api\Exception
394
     */
395
    public function sendChatAction($chatId, $action)
396
    {
397
        return $this->call('sendChatAction', [
398
            'chat_id' => $chatId,
399
            'action' => $action,
400
        ]);
401
    }
402
403
    /**
404
     * Use this method to get a list of profile pictures for a user.
405
     *
406
     * @param int $userId
407
     * @param int $offset
408
     * @param int $limit
409
     *
410
     * @return \TelegramBot\Api\Types\UserProfilePhotos
411
     * @throws \TelegramBot\Api\Exception
412
     */
413
    public function getUserProfilePhotos($userId, $offset = 0, $limit = 100)
414
    {
415
        return UserProfilePhotos::fromResponse($this->call('getUserProfilePhotos', [
416
            'user_id' => (int)$userId,
417
            'offset' => (int)$offset,
418
            'limit' => (int)$limit,
419
        ]));
420
    }
421
422
    /**
423
     * Use this method to specify a url and receive incoming updates via an outgoing webhook.
424
     * Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url,
425
     * containing a JSON-serialized Update.
426
     * In case of an unsuccessful request, we will give up after a reasonable amount of attempts.
427
     *
428
     * @param string $url HTTPS url to send updates to. Use an empty string to remove webhook integration
429
     * @param \CURLFile|string $certificate Upload your public key certificate
430
     *                                      so that the root certificate in use can be checked
431
     *
432
     * @return string
433
     *
434
     * @throws \TelegramBot\Api\Exception
435
     */
436
    public function setWebhook($url = '', $certificate = null)
437
    {
438
        return $this->call('setWebhook', ['url' => $url, 'certificate' => $certificate]);
439
    }
440
441
    /**
442
     * A simple method for testing your bot's auth token.Requires no parameters.
443
     * Returns basic information about the bot in form of a User object.
444
     *
445
     * @return \TelegramBot\Api\Types\User
446
     * @throws \TelegramBot\Api\Exception
447
     * @throws \TelegramBot\Api\InvalidArgumentException
448
     */
449
    public function getMe()
450
    {
451
        return User::fromResponse($this->call('getMe'));
452
    }
453
454
    /**
455
     * Use this method to receive incoming updates using long polling.
456
     * An Array of Update objects is returned.
457
     *
458
     * Notes
459
     * 1. This method will not work if an outgoing webhook is set up.
460
     * 2. In order to avoid getting duplicate updates, recalculate offset after each server response.
461
     *
462
     * @param int $offset
463
     * @param int $limit
464
     * @param int $timeout
465
     *
466
     * @return Update[]
467
     * @throws \TelegramBot\Api\Exception
468
     * @throws \TelegramBot\Api\InvalidArgumentException
469
     */
470 2
    public function getUpdates($offset = 0, $limit = 100, $timeout = 0)
471
    {
472 2
        $updates = ArrayOfUpdates::fromResponse($this->call('getUpdates', [
473 2
            'offset' => $offset,
474 2
            'limit' => $limit,
475 2
            'timeout' => $timeout,
476 2
        ]));
477
478 2
        if ($this->tracker instanceof Botan) {
479
            foreach ($updates as $update) {
480
                $this->trackUpdate($update);
481
            }
482
        }
483
484 2
        return $updates;
485
    }
486
487
    /**
488
     * Use this method to send point on the map. On success, the sent Message is returned.
489
     *
490
     * @param int|string                                                              $chatId
491
     * @param float                                                                   $latitude
492
     * @param float                                                                   $longitude
493
     * @param int|null                                                                $replyToMessageId
494
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
495
     *        Types\ReplyKeyboardRemove|null $replyMarkup
496
     * @param bool                                                                    $disableNotification
497
     *
498
     * @param null|int                                                                $livePeriod
499
     * @return \TelegramBot\Api\Types\Message
500
     */
501
    public function sendLocation(
502
        $chatId,
503
        $latitude,
504
        $longitude,
505
        $replyToMessageId = null,
506
        $replyMarkup = null,
507
        $disableNotification = false,
508
        $livePeriod = null
509
    ) {
510
        return Message::fromResponse($this->call('sendLocation', [
511
            'chat_id'              => $chatId,
512
            'latitude'             => $latitude,
513
            'longitude'            => $longitude,
514
            'live_period'          => $livePeriod,
515
            'reply_to_message_id'  => $replyToMessageId,
516
            'reply_markup'         => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
517
            'disable_notification' => (bool)$disableNotification,
518
        ]));
519
    }
520
521
    /**
522
     * Use this method to edit live location messages sent by the bot or via the bot (for inline bots).
523
     *
524
     * @param int|string                                                              $chatId
525
     * @param int                                                                     $messageId
526
     * @param string                                                                  $inlineMessageId
527
     * @param float                                                                   $latitude
528
     * @param float                                                                   $longitude
529
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
530
     *        Types\ReplyKeyboardRemove|null $replyMarkup
531
     * @return \TelegramBot\Api\Types\Message
532
     */
533
    public function editMessageLiveLocation(
534
        $chatId,
535
        $messageId,
536
        $inlineMessageId,
537
        $latitude,
538
        $longitude,
539
        $replyMarkup = null
540
    ) {
541
        return Message::fromResponse($this->call('sendLocation', [
542
            'chat_id'           => $chatId,
543
            'message_id'        => $messageId,
544
            'inline_message_id' => $inlineMessageId,
545
            'latitude'          => $latitude,
546
            'longitude'         => $longitude,
547
            'reply_markup'      => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
548
        ]));
549
    }
550
551
    /**
552
     * Use this method to stop updating a live location message sent by the bot or via the bot (for inline bots) before
553
     * live_period expires.
554
     *
555
     * @param int|string                                                              $chatId
556
     * @param int                                                                     $messageId
557
     * @param string                                                                  $inlineMessageId
558
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
559
     *        Types\ReplyKeyboardRemove|null $replyMarkup
560
     * @return \TelegramBot\Api\Types\Message
561
     */
562
    public function stopMessageLiveLocation(
563
        $chatId,
564
        $messageId,
565
        $inlineMessageId,
566
        $replyMarkup = null
567
    ) {
568
        return Message::fromResponse($this->call('sendLocation', [
569
            'chat_id'           => $chatId,
570
            'message_id'        => $messageId,
571
            'inline_message_id' => $inlineMessageId,
572
            'reply_markup'      => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
573
        ]));
574
    }
575
576
    /**
577
     * Use this method to send information about a venue. On success, the sent Message is returned.
578
     *
579
     * @param int|string $chatId chat_id or @channel_name
580
     * @param float $latitude
581
     * @param float $longitude
582
     * @param string $title
583
     * @param string $address
584
     * @param string|null $foursquareId
585
     * @param int|null $replyToMessageId
586
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
587
     *        Types\ReplyKeyboardRemove|null $replyMarkup
588
     * @param bool $disableNotification
589
     *
590
     * @return \TelegramBot\Api\Types\Message
591
     * @throws \TelegramBot\Api\Exception
592
     */
593
    public function sendVenue(
594
        $chatId,
595
        $latitude,
596
        $longitude,
597
        $title,
598
        $address,
599
        $foursquareId = null,
600
        $replyToMessageId = null,
601
        $replyMarkup = null,
602
        $disableNotification = false
603
    ) {
604
        return Message::fromResponse($this->call('sendVenue', [
605
            'chat_id' => $chatId,
606
            'latitude' => $latitude,
607
            'longitude' => $longitude,
608
            'title' => $title,
609
            'address' => $address,
610
            'foursquare_id' => $foursquareId,
611
            'reply_to_message_id' => $replyToMessageId,
612
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
613
            'disable_notification' => (bool)$disableNotification,
614
        ]));
615
    }
616
617
    /**
618
     * Use this method to send .webp stickers. On success, the sent Message is returned.
619
     *
620
     * @param int|string $chatId chat_id or @channel_name
621
     * @param \CURLFile|string $sticker
622
     * @param int|null $replyToMessageId
623
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
624
     *        Types\ReplyKeyboardRemove|null $replyMarkup
625
     * @param bool $disableNotification
626
     *
627
     * @return \TelegramBot\Api\Types\Message
628
     * @throws \TelegramBot\Api\InvalidArgumentException
629
     * @throws \TelegramBot\Api\Exception
630
     */
631 View Code Duplication
    public function sendSticker(
632
        $chatId,
633
        $sticker,
634
        $replyToMessageId = null,
635
        $replyMarkup = null,
636
        $disableNotification = false
637
    ) {
638
        return Message::fromResponse($this->call('sendSticker', [
639
            'chat_id' => $chatId,
640
            'sticker' => $sticker,
641
            'reply_to_message_id' => $replyToMessageId,
642
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
643
            'disable_notification' => (bool)$disableNotification,
644
        ]));
645
    }
646
647
    /**
648
     * Use this method to send video files,
649
     * Telegram clients support mp4 videos (other formats may be sent as Document).
650
     * On success, the sent Message is returned.
651
     *
652
     * @param int|string $chatId chat_id or @channel_name
653
     * @param \CURLFile|string $video
654
     * @param int|null $duration
655
     * @param string|null $caption
656
     * @param int|null $replyToMessageId
657
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
658
     *        Types\ReplyKeyboardRemove|null $replyMarkup
659
     * @param bool $disableNotification
660
     * @param bool $supportsStreaming Pass True, if the uploaded video is suitable for streaming
661
     * @param string|null $parseMode
662
     *
663
     * @return \TelegramBot\Api\Types\Message
664
     * @throws \TelegramBot\Api\InvalidArgumentException
665
     * @throws \TelegramBot\Api\Exception
666
     */
667 View Code Duplication
    public function sendVideo(
668
        $chatId,
669
        $video,
670
        $duration = null,
671
        $caption = null,
672
        $replyToMessageId = null,
673
        $replyMarkup = null,
674
        $disableNotification = false,
675
        $supportsStreaming = false,
676
        $parseMode = null
677
    ) {
678
        return Message::fromResponse($this->call('sendVideo', [
679
            'chat_id' => $chatId,
680
            'video' => $video,
681
            'duration' => $duration,
682
            'caption' => $caption,
683
            'reply_to_message_id' => $replyToMessageId,
684
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
685
            'disable_notification' => (bool)$disableNotification,
686
            'supports_streaming' => (bool)$supportsStreaming,
687
            'parse_mode' => $parseMode
688
        ]));
689
    }
690
691
    /**
692
     * Use this method to send audio files,
693
     * if you want Telegram clients to display the file as a playable voice message.
694
     * For this to work, your audio must be in an .ogg file encoded with OPUS
695
     * (other formats may be sent as Audio or Document).
696
     * On success, the sent Message is returned.
697
     * Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future.
698
     *
699
     * @param int|string $chatId chat_id or @channel_name
700
     * @param \CURLFile|string $voice
701
     * @param int|null $duration
702
     * @param int|null $replyToMessageId
703
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
704
     *        Types\ReplyKeyboardRemove|null $replyMarkup
705
     * @param bool $disableNotification
706
     * @param string|null $parseMode
707
     *
708
     * @return \TelegramBot\Api\Types\Message
709
     * @throws \TelegramBot\Api\InvalidArgumentException
710
     * @throws \TelegramBot\Api\Exception
711
     */
712
    public function sendVoice(
713
        $chatId,
714
        $voice,
715
        $duration = null,
716
        $replyToMessageId = null,
717
        $replyMarkup = null,
718
        $disableNotification = false,
719
        $parseMode = null
720
    ) {
721
        return Message::fromResponse($this->call('sendVoice', [
722
            'chat_id' => $chatId,
723
            'voice' => $voice,
724
            'duration' => $duration,
725
            'reply_to_message_id' => $replyToMessageId,
726
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
727
            'disable_notification' => (bool)$disableNotification,
728
            'parse_mode' => $parseMode
729
        ]));
730
    }
731
732
    /**
733
     * Use this method to forward messages of any kind. On success, the sent Message is returned.
734
     *
735
     * @param int|string $chatId chat_id or @channel_name
736
     * @param int $fromChatId
737
     * @param int $messageId
738
     * @param bool $disableNotification
739
     *
740
     * @return \TelegramBot\Api\Types\Message
741
     * @throws \TelegramBot\Api\InvalidArgumentException
742
     * @throws \TelegramBot\Api\Exception
743
     */
744
    public function forwardMessage($chatId, $fromChatId, $messageId, $disableNotification = false)
745
    {
746
        return Message::fromResponse($this->call('forwardMessage', [
747
            'chat_id' => $chatId,
748
            'from_chat_id' => $fromChatId,
749
            'message_id' => (int)$messageId,
750
            'disable_notification' => (bool)$disableNotification,
751
        ]));
752
    }
753
754
    /**
755
     * Use this method to send audio files,
756
     * if you want Telegram clients to display them in the music player.
757
     * Your audio must be in the .mp3 format.
758
     * On success, the sent Message is returned.
759
     * Bots can currently send audio files of up to 50 MB in size, this limit may be changed in the future.
760
     *
761
     * For backward compatibility, when the fields title and performer are both empty
762
     * and the mime-type of the file to be sent is not audio/mpeg, the file will be sent as a playable voice message.
763
     * For this to work, the audio must be in an .ogg file encoded with OPUS.
764
     * This behavior will be phased out in the future. For sending voice messages, use the sendVoice method instead.
765
     *
766
     * @deprecated since 20th February. Removed backward compatibility from the method sendAudio.
767
     * Voice messages now must be sent using the method sendVoice.
768
     * There is no more need to specify a non-empty title or performer while sending the audio by file_id.
769
     *
770
     * @param int|string $chatId chat_id or @channel_name
771
     * @param \CURLFile|string $audio
772
     * @param int|null $duration
773
     * @param string|null $performer
774
     * @param string|null $title
775
     * @param int|null $replyToMessageId
776
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
777
     *        Types\ReplyKeyboardRemove|null $replyMarkup
778
     * @param bool $disableNotification
779
     * @param string|null $parseMode
780
     *
781
     * @return \TelegramBot\Api\Types\Message
782
     * @throws \TelegramBot\Api\InvalidArgumentException
783
     * @throws \TelegramBot\Api\Exception
784
     */
785 View Code Duplication
    public function sendAudio(
786
        $chatId,
787
        $audio,
788
        $duration = null,
789
        $performer = null,
790
        $title = null,
791
        $replyToMessageId = null,
792
        $replyMarkup = null,
793
        $disableNotification = false,
794
        $parseMode = null
795
    ) {
796
        return Message::fromResponse($this->call('sendAudio', [
797
            'chat_id' => $chatId,
798
            'audio' => $audio,
799
            'duration' => $duration,
800
            'performer' => $performer,
801
            'title' => $title,
802
            'reply_to_message_id' => $replyToMessageId,
803
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
804
            'disable_notification' => (bool)$disableNotification,
805
            'parse_mode' => $parseMode
806
        ]));
807
    }
808
809
    /**
810
     * Use this method to send photos. On success, the sent Message is returned.
811
     *
812
     * @param int|string $chatId chat_id or @channel_name
813
     * @param \CURLFile|string $photo
814
     * @param string|null $caption
815
     * @param int|null $replyToMessageId
816
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
817
     *        Types\ReplyKeyboardRemove|null $replyMarkup
818
     * @param bool $disableNotification
819
     * @param string|null $parseMode
820
     *
821
     * @return \TelegramBot\Api\Types\Message
822
     * @throws \TelegramBot\Api\InvalidArgumentException
823
     * @throws \TelegramBot\Api\Exception
824
     */
825
    public function sendPhoto(
826
        $chatId,
827
        $photo,
828
        $caption = null,
829
        $replyToMessageId = null,
830
        $replyMarkup = null,
831
        $disableNotification = false,
832
        $parseMode = null
833
    ) {
834
        return Message::fromResponse($this->call('sendPhoto', [
835
            'chat_id' => $chatId,
836
            'photo' => $photo,
837
            'caption' => $caption,
838
            'reply_to_message_id' => $replyToMessageId,
839
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
840
            'disable_notification' => (bool)$disableNotification,
841
            'parse_mode' => $parseMode
842
        ]));
843
    }
844
845
    /**
846
     * Use this method to send general files. On success, the sent Message is returned.
847
     * Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future.
848
     *
849
     * @param int|string $chatId chat_id or @channel_name
850
     * @param \CURLFile|string $document
851
     * @param string|null $caption
852
     * @param int|null $replyToMessageId
853
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
854
     *        Types\ReplyKeyboardRemove|null $replyMarkup
855
     * @param bool $disableNotification
856
     * @param string|null $parseMode
857
     *
858
     * @return \TelegramBot\Api\Types\Message
859
     * @throws \TelegramBot\Api\InvalidArgumentException
860
     * @throws \TelegramBot\Api\Exception
861
     */
862
    public function sendDocument(
863
        $chatId,
864
        $document,
865
        $caption = null,
866
        $replyToMessageId = null,
867
        $replyMarkup = null,
868
        $disableNotification = false,
869
        $parseMode = null
870
    ) {
871
        return Message::fromResponse($this->call('sendDocument', [
872
            'chat_id' => $chatId,
873
            'document' => $document,
874
            'caption' => $caption,
875
            'reply_to_message_id' => $replyToMessageId,
876
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
877
            'disable_notification' => (bool)$disableNotification,
878
            'parse_mode' => $parseMode
879
        ]));
880
    }
881
882
    /**
883
     * Use this method to get basic info about a file and prepare it for downloading.
884
     * For the moment, bots can download files of up to 20MB in size.
885
     * On success, a File object is returned.
886
     * The file can then be downloaded via the link https://api.telegram.org/file/bot<token>/<file_path>,
887
     * where <file_path> is taken from the response.
888
     * It is guaranteed that the link will be valid for at least 1 hour.
889
     * When the link expires, a new one can be requested by calling getFile again.
890
     *
891
     * @param $fileId
892
     *
893
     * @return \TelegramBot\Api\Types\File
894
     * @throws \TelegramBot\Api\InvalidArgumentException
895
     * @throws \TelegramBot\Api\Exception
896
     */
897
    public function getFile($fileId)
898
    {
899
        return File::fromResponse($this->call('getFile', ['file_id' => $fileId]));
900
    }
901
902
    /**
903
     * Get file contents via cURL
904
     *
905
     * @param $fileId
906
     *
907
     * @return string
908
     *
909
     * @throws \TelegramBot\Api\HttpException
910
     */
911
    public function downloadFile($fileId)
912
    {
913
        $file = $this->getFile($fileId);
914
        $options = [
915
            CURLOPT_HEADER => 0,
916
            CURLOPT_HTTPGET => 1,
917
            CURLOPT_RETURNTRANSFER => 1,
918
            CURLOPT_URL => $this->getFileUrl().'/'.$file->getFilePath(),
919
        ];
920
921
        return $this->executeCurl($options);
922
    }
923
924
    /**
925
     * Use this method to send answers to an inline query. On success, True is returned.
926
     * No more than 50 results per query are allowed.
927
     *
928
     * @param string $inlineQueryId
929
     * @param AbstractInlineQueryResult[] $results
930
     * @param int $cacheTime
931
     * @param bool $isPersonal
932
     * @param string $nextOffset
933
     * @param string $switchPmText
934
     * @param string $switchPmParameter
935
     *
936
     * @return mixed
937
     * @throws Exception
938
     */
939
    public function answerInlineQuery(
940
        $inlineQueryId,
941
        $results,
942
        $cacheTime = 300,
943
        $isPersonal = false,
944
        $nextOffset = '',
945
        $switchPmText = null,
946
        $switchPmParameter = null
947
    ) {
948
        $results = array_map(function ($item) {
949
            /* @var AbstractInlineQueryResult $item */
950
            return json_decode($item->toJson(), true);
951
        }, $results);
952
953
        return $this->call('answerInlineQuery', [
954
            'inline_query_id' => $inlineQueryId,
955
            'results' => json_encode($results),
956
            'cache_time' => $cacheTime,
957
            'is_personal' => $isPersonal,
958
            'next_offset' => $nextOffset,
959
            'switch_pm_text' => $switchPmText,
960
            'switch_pm_parameter' => $switchPmParameter,
961
        ]);
962
    }
963
964
    /**
965
     * Use this method to kick a user from a group or a supergroup.
966
     * In the case of supergroups, the user will not be able to return to the group
967
     * on their own using invite links, etc., unless unbanned first.
968
     * The bot must be an administrator in the group for this to work. Returns True on success.
969
     *
970
     * @param int|string $chatId Unique identifier for the target group
971
     * or username of the target supergroup (in the format @supergroupusername)
972
     * @param int $userId Unique identifier of the target user
973
     * @param null|int $untilDate Date when the user will be unbanned, unix time.
974
     *                            If user is banned for more than 366 days or less than 30 seconds from the current time
975
     *                            they are considered to be banned forever
976
     *
977
     * @return bool
978
     */
979
    public function kickChatMember($chatId, $userId, $untilDate = null)
980
    {
981
        return $this->call('kickChatMember', [
982
            'chat_id' => $chatId,
983
            'user_id' => $userId,
984
            'until_date' => $untilDate
985
        ]);
986
    }
987
988
    /**
989
     * Use this method to unban a previously kicked user in a supergroup.
990
     * The user will not return to the group automatically, but will be able to join via link, etc.
991
     * The bot must be an administrator in the group for this to work. Returns True on success.
992
     *
993
     * @param int|string $chatId Unique identifier for the target group
994
     * or username of the target supergroup (in the format @supergroupusername)
995
     * @param int $userId Unique identifier of the target user
996
     *
997
     * @return bool
998
     */
999
    public function unbanChatMember($chatId, $userId)
1000
    {
1001
        return $this->call('unbanChatMember', [
1002
            'chat_id' => $chatId,
1003
            'user_id' => $userId,
1004
        ]);
1005
    }
1006
1007
    /**
1008
     * Use this method to send answers to callback queries sent from inline keyboards.
1009
     * The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.
1010
     *
1011
     * @param $callbackQueryId
1012
     * @param null $text
1013
     * @param bool $showAlert
1014
     *
1015
     * @return bool
1016
     */
1017
    public function answerCallbackQuery($callbackQueryId, $text = null, $showAlert = false)
1018
    {
1019
        return $this->call('answerCallbackQuery', [
1020
            'callback_query_id' => $callbackQueryId,
1021
            'text' => $text,
1022
            'show_alert' => (bool)$showAlert,
1023
        ]);
1024
    }
1025
1026
1027
    /**
1028
     * Use this method to edit text messages sent by the bot or via the bot
1029
     *
1030
     * @param int|string $chatId
1031
     * @param int $messageId
1032
     * @param string $text
1033
     * @param string $inlineMessageId
1034
     * @param string|null $parseMode
1035
     * @param bool $disablePreview
1036
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1037
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1038
     * @return Message
1039
     */
1040
    public function editMessageText(
1041
        $chatId,
1042
        $messageId,
1043
        $text,
1044
        $parseMode = null,
1045
        $disablePreview = false,
1046
        $replyMarkup = null,
1047
        $inlineMessageId = null
1048
    ) {
1049
        return Message::fromResponse($this->call('editMessageText', [
1050
            'chat_id' => $chatId,
1051
            'message_id' => $messageId,
1052
            'text' => $text,
1053
            'inline_message_id' => $inlineMessageId,
1054
            'parse_mode' => $parseMode,
1055
            'disable_web_page_preview' => $disablePreview,
1056
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1057
        ]));
1058
    }
1059
1060
    /**
1061
     * Use this method to edit text messages sent by the bot or via the bot
1062
     *
1063
     * @param int|string $chatId
1064
     * @param int $messageId
1065
     * @param string|null $caption
1066
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1067
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1068
     * @param string $inlineMessageId
1069
     *
1070
     * @return \TelegramBot\Api\Types\Message
1071
     * @throws \TelegramBot\Api\InvalidArgumentException
1072
     * @throws \TelegramBot\Api\Exception
1073
     */
1074 View Code Duplication
    public function editMessageCaption(
1075
        $chatId,
1076
        $messageId,
1077
        $caption = null,
1078
        $replyMarkup = null,
1079
        $inlineMessageId = null
1080
    ) {
1081
        return Message::fromResponse($this->call('editMessageCaption', [
1082
            'chat_id' => $chatId,
1083
            'message_id' => $messageId,
1084
            'inline_message_id' => $inlineMessageId,
1085
            'caption' => $caption,
1086
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1087
        ]));
1088
    }
1089
1090
    /**
1091
     * Use this method to edit only the reply markup of messages sent by the bot or via the bot
1092
     *
1093
     * @param int|string $chatId
1094
     * @param int $messageId
1095
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1096
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1097
     * @param string $inlineMessageId
1098
     *
1099
     * @return Message
1100
     */
1101
    public function editMessageReplyMarkup(
1102
        $chatId,
1103
        $messageId,
1104
        $replyMarkup = null,
1105
        $inlineMessageId = null
1106
    ) {
1107
        return Message::fromResponse($this->call('editMessageReplyMarkup', [
1108
            'chat_id' => $chatId,
1109
            'message_id' => $messageId,
1110
            'inline_message_id' => $inlineMessageId,
1111
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1112
        ]));
1113
    }
1114
1115
    /**
1116
     * Use this method to delete a message, including service messages, with the following limitations:
1117
     *  - A message can only be deleted if it was sent less than 48 hours ago.
1118
     *  - Bots can delete outgoing messages in groups and supergroups.
1119
     *  - Bots granted can_post_messages permissions can delete outgoing messages in channels.
1120
     *  - If the bot is an administrator of a group, it can delete any message there.
1121
     *  - If the bot has can_delete_messages permission in a supergroup or a channel, it can delete any message there.
1122
     *
1123
     * @param int|string $chatId
1124
     * @param int $messageId
1125
     *
1126
     * @return bool
1127
     */
1128
    public function deleteMessage($chatId, $messageId)
1129
    {
1130
        return $this->call('deleteMessage', [
1131
            'chat_id' => $chatId,
1132
            'message_id' => $messageId,
1133
        ]);
1134
    }
1135
1136
    /**
1137
     * Close curl
1138
     */
1139 9
    public function __destruct()
1140
    {
1141 9
        $this->curl && curl_close($this->curl);
1142 9
    }
1143
1144
    /**
1145
     * @return string
1146
     */
1147
    public function getUrl()
1148
    {
1149
        return self::URL_PREFIX.$this->token;
1150
    }
1151
1152
    /**
1153
     * @return string
1154
     */
1155
    public function getFileUrl()
1156
    {
1157
        return self::FILE_URL_PREFIX.$this->token;
1158
    }
1159
1160
    /**
1161
     * @param \TelegramBot\Api\Types\Update $update
1162
     * @param string $eventName
1163
     *
1164
     * @throws \TelegramBot\Api\Exception
1165
     */
1166
    public function trackUpdate(Update $update, $eventName = 'Message')
1167
    {
1168
        if (!in_array($update->getUpdateId(), $this->trackedEvents)) {
1169
            $this->trackedEvents[] = $update->getUpdateId();
1170
1171
            $this->track($update->getMessage(), $eventName);
1172
1173
            if (count($this->trackedEvents) > self::MAX_TRACKED_EVENTS) {
1174
                $this->trackedEvents = array_slice($this->trackedEvents, round(self::MAX_TRACKED_EVENTS / 4));
1175
            }
1176
        }
1177
    }
1178
1179
    /**
1180
     * Wrapper for tracker
1181
     *
1182
     * @param \TelegramBot\Api\Types\Message $message
1183
     * @param string $eventName
1184
     *
1185
     * @throws \TelegramBot\Api\Exception
1186
     */
1187
    public function track(Message $message, $eventName = 'Message')
1188
    {
1189
        if ($this->tracker instanceof Botan) {
1190
            $this->tracker->track($message, $eventName);
1191
        }
1192
    }
1193
1194
    /**
1195
     * Use this method to send invoices. On success, the sent Message is returned.
1196
     *
1197
     * @param int|string $chatId
1198
     * @param string $title
1199
     * @param string $description
1200
     * @param string $payload
1201
     * @param string $providerToken
1202
     * @param string $startParameter
1203
     * @param string $currency
1204
     * @param array $prices
1205
     * @param string|null $photoUrl
1206
     * @param int|null $photoSize
1207
     * @param int|null $photoWidth
1208
     * @param int|null $photoHeight
1209
     * @param bool $needName
1210
     * @param bool $needPhoneNumber
1211
     * @param bool $needEmail
1212
     * @param bool $needShippingAddress
1213
     * @param bool $isFlexible
1214
     * @param int|null $replyToMessageId
1215
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1216
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1217
     * @param bool $disableNotification
1218
     * @param string|null $providerData
1219
     * @param bool $sendPhoneNumberToProvider
1220
     * @param bool $sendEmailToProvider
1221
     *
1222
     * @return Message
1223
     */
1224
    public function sendInvoice(
1225
        $chatId,
1226
        $title,
1227
        $description,
1228
        $payload,
1229
        $providerToken,
1230
        $startParameter,
1231
        $currency,
1232
        $prices,
1233
        $isFlexible = false,
1234
        $photoUrl = null,
1235
        $photoSize = null,
1236
        $photoWidth = null,
1237
        $photoHeight = null,
1238
        $needName = false,
1239
        $needPhoneNumber = false,
1240
        $needEmail = false,
1241
        $needShippingAddress = false,
1242
        $replyToMessageId = null,
1243
        $replyMarkup = null,
1244
        $disableNotification = false,
1245
        $providerData = null,
1246
        $sendPhoneNumberToProvider = false,
1247
        $sendEmailToProvider = false
1248
    ) {
1249
        return Message::fromResponse($this->call('sendInvoice', [
1250
            'chat_id' => $chatId,
1251
            'title' => $title,
1252
            'description' => $description,
1253
            'payload' => $payload,
1254
            'provider_token' => $providerToken,
1255
            'start_parameter' => $startParameter,
1256
            'currency' => $currency,
1257
            'prices' => json_encode($prices),
1258
            'is_flexible' => $isFlexible,
1259
            'photo_url' => $photoUrl,
1260
            'photo_size' => $photoSize,
1261
            'photo_width' => $photoWidth,
1262
            'photo_height' => $photoHeight,
1263
            'need_name' => $needName,
1264
            'need_phone_number' => $needPhoneNumber,
1265
            'need_email' => $needEmail,
1266
            'need_shipping_address' => $needShippingAddress,
1267
            'reply_to_message_id' => $replyToMessageId,
1268
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1269
            'disable_notification' => (bool)$disableNotification,
1270
            'provider_data' => $providerData,
1271
            'send_phone_number_to_provider' => (bool)$sendPhoneNumberToProvider,
1272
            'send_email_to_provider' => (bool)$sendEmailToProvider
1273
        ]));
1274
    }
1275
1276
    /**
1277
     * If you sent an invoice requesting a shipping address and the parameter is_flexible was specified, the Bot API
1278
     * will send an Update with a shipping_query field to the bot. Use this method to reply to shipping queries.
1279
     * On success, True is returned.
1280
     *
1281
     * @param string $shippingQueryId
1282
     * @param bool $ok
1283
     * @param array $shipping_options
1284
     * @param null|string $errorMessage
1285
     *
1286
     * @return bool
1287
     *
1288
     */
1289
    public function answerShippingQuery($shippingQueryId, $ok = true, $shipping_options = [], $errorMessage = null)
1290
    {
1291
        return $this->call('answerShippingQuery', [
1292
            'shipping_query_id' => $shippingQueryId,
1293
            'ok' => (bool)$ok,
1294
            'shipping_options' => json_encode($shipping_options),
1295
            'error_message' => $errorMessage
1296
        ]);
1297
    }
1298
1299
    /**
1300
     * Use this method to respond to such pre-checkout queries. On success, True is returned.
1301
     * Note: The Bot API must receive an answer within 10 seconds after the pre-checkout query was sent.
1302
     *
1303
     * @param string $preCheckoutQueryId
1304
     * @param bool $ok
1305
     * @param null|string $errorMessage
1306
     *
1307
     * @return mixed
1308
     */
1309
    public function answerPreCheckoutQuery($preCheckoutQueryId, $ok = true, $errorMessage = null)
1310
    {
1311
        return $this->call('answerPreCheckoutQuery', [
1312
            'pre_checkout_query_id' => $preCheckoutQueryId,
1313
            'ok' => (bool)$ok,
1314
            'error_message' => $errorMessage
1315
        ]);
1316
    }
1317
1318
    /**
1319
     * Use this method to restrict a user in a supergroup.
1320
     * The bot must be an administrator in the supergroup for this to work and must have the appropriate admin rights.
1321
     * Pass True for all boolean parameters to lift restrictions from a user.
1322
     *
1323
     * @param string|int $chatId Unique identifier for the target chat or username of the target supergroup
1324
     *                   (in the format @supergroupusername)
1325
     * @param int $userId Unique identifier of the target user
1326
     * @param null|integer $untilDate Date when restrictions will be lifted for the user, unix time.
1327
     *                     If user is restricted for more than 366 days or less than 30 seconds from the current time,
1328
     *                     they are considered to be restricted forever
1329
     * @param bool $canSendMessages Pass True, if the user can send text messages, contacts, locations and venues
1330
     * @param bool $canSendMediaMessages No Pass True, if the user can send audios, documents, photos, videos,
1331
     *                                   video notes and voice notes, implies can_send_messages
1332
     * @param bool $canSendOtherMessages Pass True, if the user can send animations, games, stickers and
1333
     *                                   use inline bots, implies can_send_media_messages
1334
     * @param bool $canAddWebPagePreviews Pass True, if the user may add web page previews to their messages,
1335
     *                                    implies can_send_media_messages
1336
     *
1337
     * @return bool
1338
     */
1339
    public function restrictChatMember(
1340
        $chatId,
1341
        $userId,
1342
        $untilDate = null,
1343
        $canSendMessages = false,
1344
        $canSendMediaMessages = false,
1345
        $canSendOtherMessages = false,
1346
        $canAddWebPagePreviews = false
1347
    ) {
1348
        return $this->call('restrictChatMember', [
1349
            'chat_id' => $chatId,
1350
            'user_id' => $userId,
1351
            'until_date' => $untilDate,
1352
            'can_send_messages' => $canSendMessages,
1353
            'can_send_media_messages' => $canSendMediaMessages,
1354
            'can_send_other_messages' => $canSendOtherMessages,
1355
            'can_add_web_page_previews' => $canAddWebPagePreviews
1356
        ]);
1357
    }
1358
1359
    /**
1360
     * Use this method to promote or demote a user in a supergroup or a channel.
1361
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1362
     * Pass False for all boolean parameters to demote a user.
1363
     *
1364
     * @param string|int $chatId Unique identifier for the target chat or username of the target supergroup
1365
     *                   (in the format @supergroupusername)
1366
     * @param int $userId Unique identifier of the target user
1367
     * @param bool $canChangeInfo Pass True, if the administrator can change chat title, photo and other settings
1368
     * @param bool $canPostMessages Pass True, if the administrator can create channel posts, channels only
1369
     * @param bool $canEditMessages Pass True, if the administrator can edit messages of other users, channels only
1370
     * @param bool $canDeleteMessages Pass True, if the administrator can delete messages of other users
1371
     * @param bool $canInviteUsers Pass True, if the administrator can invite new users to the chat
1372
     * @param bool $canRestrictMembers Pass True, if the administrator can restrict, ban or unban chat members
1373
     * @param bool $canPinMessages Pass True, if the administrator can pin messages, supergroups only
1374
     * @param bool $canPromoteMembers Pass True, if the administrator can add new administrators with a subset of his
1375
     *                                own privileges or demote administrators that he has promoted,directly or
1376
     *                                indirectly (promoted by administrators that were appointed by him)
1377
     *
1378
     * @return bool
1379
     */
1380
    public function promoteChatMember(
1381
        $chatId,
1382
        $userId,
1383
        $canChangeInfo = true,
1384
        $canPostMessages = true,
1385
        $canEditMessages = true,
1386
        $canDeleteMessages = true,
1387
        $canInviteUsers = true,
1388
        $canRestrictMembers = true,
1389
        $canPinMessages = true,
1390
        $canPromoteMembers = true
1391
    ) {
1392
        return $this->call('promoteChatMember', [
1393
            'chat_id' => $chatId,
1394
            'user_id' => $userId,
1395
            'can_change_info' => $canChangeInfo,
1396
            'can_post_messages' => $canPostMessages,
1397
            'can_edit_messages' => $canEditMessages,
1398
            'can_delete_messages' => $canDeleteMessages,
1399
            'can_invite_users' => $canInviteUsers,
1400
            'can_restrict_members' => $canRestrictMembers,
1401
            'can_pin_messages' => $canPinMessages,
1402
            'can_promote_members' => $canPromoteMembers
1403
        ]);
1404
    }
1405
1406
    /**
1407
     * Use this method to export an invite link to a supergroup or a channel.
1408
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1409
     *
1410
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1411
     *                           (in the format @channelusername)
1412
     * @return string
1413
     */
1414
    public function exportChatInviteLink($chatId)
1415
    {
1416
        return $this->call('exportChatInviteLink', [
1417
            'chat_id' => $chatId
1418
        ]);
1419
    }
1420
1421
    /**
1422
     * Use this method to set a new profile photo for the chat. Photos can't be changed for private chats.
1423
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1424
     *
1425
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1426
     *                           (in the format @channelusername)
1427
     * @param \CURLFile|string $photo New chat photo, uploaded using multipart/form-data
1428
     *
1429
     * @return bool
1430
     */
1431
    public function setChatPhoto($chatId, $photo)
1432
    {
1433
        return $this->call('setChatPhoto', [
1434
            'chat_id' => $chatId,
1435
            'photo' => $photo
1436
        ]);
1437
    }
1438
1439
    /**
1440
     * Use this method to delete a chat photo. Photos can't be changed for private chats.
1441
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1442
     *
1443
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1444
     *                           (in the format @channelusername)
1445
     *
1446
     * @return bool
1447
     */
1448
    public function deleteChatPhoto($chatId)
1449
    {
1450
        return $this->call('deleteChatPhoto', [
1451
            'chat_id' => $chatId
1452
        ]);
1453
    }
1454
1455
    /**
1456
     * Use this method to change the title of a chat. Titles can't be changed for private chats.
1457
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1458
     *
1459
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1460
     *                           (in the format @channelusername)
1461
     * @param string $title New chat title, 1-255 characters
1462
     *
1463
     * @return bool
1464
     */
1465
    public function setChatTitle($chatId, $title)
1466
    {
1467
        return $this->call('setChatTitle', [
1468
            'chat_id' => $chatId,
1469
            'title' => $title
1470
        ]);
1471
    }
1472
1473
    /**
1474
     * Use this method to change the description of a supergroup or a channel.
1475
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1476
     *
1477
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1478
     *                   (in the format @channelusername)
1479
     * @param string|null $description New chat description, 0-255 characters
1480
     *
1481
     * @return bool
1482
     */
1483
    public function setChatDescription($chatId, $description = null)
1484
    {
1485
        return $this->call('setChatDescription', [
1486
            'chat_id' => $chatId,
1487
            'title' => $description
1488
        ]);
1489
    }
1490
1491
    /**
1492
     * Use this method to pin a message in a supergroup.
1493
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1494
     *
1495
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1496
     *                   (in the format @channelusername)
1497
     * @param int $messageId Identifier of a message to pin
1498
     * @param bool $disableNotification
1499
     *
1500
     * @return bool
1501
     */
1502
    public function pinChatMessage($chatId, $messageId, $disableNotification = false)
1503
    {
1504
        return $this->call('pinChatMessage', [
1505
            'chat_id' => $chatId,
1506
            'message_id' => $messageId,
1507
            'disable_notification' => $disableNotification
1508
        ]);
1509
    }
1510
1511
    /**
1512
     * Use this method to unpin a message in a supergroup chat.
1513
     * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
1514
     *
1515
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1516
     *                   (in the format @channelusername)
1517
     *
1518
     * @return bool
1519
     */
1520
    public function unpinChatMessage($chatId)
1521
    {
1522
        return $this->call('unpinChatMessage', [
1523
            'chat_id' => $chatId
1524
        ]);
1525
    }
1526
1527
    /**
1528
     * Use this method to get up to date information about the chat
1529
     * (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.).
1530
     *
1531
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1532
     *                   (in the format @channelusername)
1533
     *
1534
     * @return Chat
1535
     */
1536
    public function getChat($chatId)
1537
    {
1538
        return Chat::fromResponse($this->call('getChat', [
1539
            'chat_id' => $chatId
1540
        ]));
1541
    }
1542
1543
    /**
1544
     * Use this method to get information about a member of a chat.
1545
     *
1546
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1547
     *                   (in the format @channelusername)
1548
     * @param int $userId
1549
     *
1550
     * @return ChatMember
1551
     */
1552
    public function getChatMember($chatId, $userId)
1553
    {
1554
        return ChatMember::fromResponse($this->call('getChatMember', [
1555
            'chat_id' => $chatId,
1556
            'user_id' => $userId
1557
        ]));
1558
    }
1559
1560
    /**
1561
     * Use this method for your bot to leave a group, supergroup or channel.
1562
     *
1563
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1564
     *                   (in the format @channelusername)
1565
     *
1566
     * @return bool
1567
     */
1568
    public function leaveChat($chatId)
1569
    {
1570
        return $this->call('leaveChat', [
1571
            'chat_id' => $chatId
1572
        ]);
1573
    }
1574
1575
    /**
1576
     * Use this method to get the number of members in a chat.
1577
     *
1578
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1579
     *                   (in the format @channelusername)
1580
     *
1581
     * @return int
1582
     */
1583
    public function getChatMembersCount($chatId)
1584
    {
1585
        return $this->call(
1586
            'getChatMembersCount',
1587
            [
1588
                'chat_id' => $chatId
1589
            ]
1590
        );
1591
    }
1592
1593
    /**
1594
     * Use this method to get a list of administrators in a chat.
1595
     *
1596
     * @param string|int $chatId Unique identifier for the target chat or username of the target channel
1597
     *                   (in the format @channelusername)
1598
     *
1599
     * @return array
1600
     */
1601
    public function getChatAdministrators($chatId)
1602
    {
1603
        return ArrayOfChatMemberEntity::fromResponse(
1604
            $this->call(
1605
                'getChatAdministrators',
1606
                [
1607
                    'chat_id' => $chatId
1608
                ]
1609
            )
1610
        );
1611
    }
1612
1613
    /**
1614
     * As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1 minute long.
1615
     * Use this method to send video messages.
1616
     * On success, the sent Message is returned.
1617
     *
1618
     * @param int|string $chatId chat_id or @channel_name
1619
     * @param \CURLFile|string $videoNote
1620
     * @param int|null $duration
1621
     * @param int|null $length
1622
     * @param int|null $replyToMessageId
1623
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1624
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1625
     * @param bool $disableNotification
1626
     *
1627
     * @return \TelegramBot\Api\Types\Message
1628
     * @throws \TelegramBot\Api\InvalidArgumentException
1629
     * @throws \TelegramBot\Api\Exception
1630
     */
1631
    public function sendVideoNote(
1632
        $chatId,
1633
        $videoNote,
1634
        $duration = null,
1635
        $length = null,
1636
        $replyToMessageId = null,
1637
        $replyMarkup = null,
1638
        $disableNotification = false
1639
    ) {
1640
        return Message::fromResponse($this->call('sendVideoNote', [
1641
            'chat_id' => $chatId,
1642
            'video_note' => $videoNote,
1643
            'duration' => $duration,
1644
            'length' => $length,
1645
            'reply_to_message_id' => $replyToMessageId,
1646
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1647
            'disable_notification' => (bool)$disableNotification
1648
        ]));
1649
    }
1650
1651
    /**
1652
     * Use this method to send a group of photos or videos as an album.
1653
     * On success, the sent \TelegramBot\Api\Types\Message is returned.
1654
     *
1655
     * @param int|string $chatId
1656
     * @param ArrayOfInputMedia $media
1657
     * @param int|null $replyToMessageId
1658
     * @param bool $disableNotification
1659
     *
1660
     * @return array
1661
     * @throws \TelegramBot\Api\Exception
1662
     */
1663
    public function sendMediaGroup(
1664
        $chatId,
1665
        $media,
1666
        $disableNotification = false,
1667
        $replyToMessageId = null
1668
    ) {
1669
        return ArrayOfMessages::fromResponse($this->call('sendMediaGroup', [
1670
            'chat_id' => $chatId,
1671
            'media' => $media->toJson(),
1672
            'reply_to_message_id' => (int)$replyToMessageId,
1673
            'disable_notification' => (bool)$disableNotification
1674
        ]));
1675
    }
1676
1677
    /**
1678
     * Enable proxy for curl requests. Empty string will disable proxy.
1679
     *
1680
     * @param string $proxyString
1681
     *
1682
     * @return BotApi
1683
     */
1684
    public function setProxy($proxyString = '', $socks5 = false)
1685
    {
1686
        if (empty($proxyString)) {
1687
            $this->proxySettings = [];
1688
            return $this;
1689
        }
1690
1691
        $this->proxySettings = [
1692
            CURLOPT_PROXY => $proxyString,
1693
            CURLOPT_HTTPPROXYTUNNEL => true,
1694
        ];
1695
        
1696
        if ($socks5) {
1697
            $this->proxySettings[CURLOPT_PROXYTYPE] = CURLPROXY_SOCKS5;
1698
        }
1699
        return $this;
1700
    }
1701
1702
1703
    /**
1704
     * Use this method to send a native poll. A native poll can't be sent to a private chat. On success, the sent \TelegramBot\Api\Types\Message is returned.
1705
     *
1706
     * @param int|string $chatId
1707
     * @param string $question
1708
     * @param array $options
1709
     * @param bool $disableNotification
1710
     * @param int|null $replyToMessageId
1711
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1712
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1713
     *
1714
     * @return \TelegramBot\Api\Types\Message
1715
     * @throws \TelegramBot\Api\InvalidArgumentException
1716
     * @throws \TelegramBot\Api\Exception
1717
     */
1718 View Code Duplication
    public function sendPoll(
1719
        $chatId,
1720
        $question,
1721
        $options,
1722
        $disableNotification = false,
1723
        $replyToMessageId = null,
1724
        $replyMarkup = null
1725
    ) {
1726
        return Message::fromResponse($this->call('sendPoll', [
1727
            'chat_id' => $chatId,
1728
            'question' => $question,
1729
            'options' => json_encode($options),
1730
            'disable_notification' => (bool)$disableNotification,
1731
            'reply_to_message_id' => (int)$replyToMessageId,
1732
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1733
        ]));
1734
    }
1735
1736
    /**
1737
     * Use this method to stop a poll which was sent by the bot. On success, the stopped \TelegramBot\Api\Types\Poll with the final results is returned.
1738
     *
1739
     * @param int|string $chatId
1740
     * @param int $messageId
1741
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|
1742
     *        Types\ReplyKeyboardRemove|null $replyMarkup
1743
     * @return Poll
1744
     * @throws \TelegramBot\Api\InvalidArgumentException
1745
     * @throws \TelegramBot\Api\Exception
1746
     */
1747
    public function stopPoll(
1748
        $chatId,
1749
        $messageId,
1750
        $replyMarkup = null
1751
    ) {
1752
        return Poll::fromResponse($this->call('stopPoll', [
1753
            'chat_id' => $chatId,
1754
            'message_id' => $messageId,
1755
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1756
        ]));
1757
    }
1758
1759
    /**
1760
     * Set an option for a cURL transfer
1761
     *
1762
     * @param int $option The CURLOPT_XXX option to set
1763
     * @param mixed $value The value to be set on option
1764
     */
1765
    public function setCurlOption($option, $value)
1766
    {
1767
        $this->customCurlOptions[$option] = $value;
1768
    }
1769
1770
    /**
1771
     * Unset an option for a cURL transfer
1772
     *
1773
     * @param int $option The CURLOPT_XXX option to unset
1774
     */
1775
    public function unsetCurlOption($option)
1776
    {
1777
        unset($this->customCurlOptions[$option]);
1778
    }
1779
1780
    /**
1781
     * Clean custom options
1782
     */
1783
    public function resetCurlOptions()
1784
    {
1785
        $this->customCurlOptions = [];
1786
    }
1787
}
1788