Passed
Push — master ( b93506...d41428 )
by
unknown
01:39
created

BotApi::setProxy()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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