Completed
Push — master ( cc5700...07936d )
by Gusev
05:58 queued 03:09
created

BotApi::editMessageReplyMarkup()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 11
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 11
loc 11
ccs 0
cts 6
cp 0
rs 9.4285
cc 2
eloc 8
nc 1
nop 3
crap 6
1
<?php
2
3
namespace TelegramBot\Api;
4
5
use TelegramBot\Api\Types\ArrayOfUpdates;
6
use TelegramBot\Api\Types\File;
7
use TelegramBot\Api\Types\Message;
8
use TelegramBot\Api\Types\Update;
9
use TelegramBot\Api\Types\User;
10
use TelegramBot\Api\Types\UserProfilePhotos;
11
12
/**
13
 * Class BotApi
14
 *
15
 * @package TelegramBot\Api
16
 */
17
class BotApi
18
{
19
    /**
20
     * HTTP codes
21
     *
22
     * @var array
23
     */
24
    public static $codes = [
25
        // Informational 1xx
26
        100 => 'Continue',
27
        101 => 'Switching Protocols',
28
        102 => 'Processing',            // RFC2518
29
        // Success 2xx
30
        200 => 'OK',
31
        201 => 'Created',
32
        202 => 'Accepted',
33
        203 => 'Non-Authoritative Information',
34
        204 => 'No Content',
35
        205 => 'Reset Content',
36
        206 => 'Partial Content',
37
        207 => 'Multi-Status',          // RFC4918
38
        208 => 'Already Reported',      // RFC5842
39
        226 => 'IM Used',               // RFC3229
40
        // Redirection 3xx
41
        300 => 'Multiple Choices',
42
        301 => 'Moved Permanently',
43
        302 => 'Found', // 1.1
44
        303 => 'See Other',
45
        304 => 'Not Modified',
46
        305 => 'Use Proxy',
47
        // 306 is deprecated but reserved
48
        307 => 'Temporary Redirect',
49
        308 => 'Permanent Redirect',    // RFC7238
50
        // Client Error 4xx
51
        400 => 'Bad Request',
52
        401 => 'Unauthorized',
53
        402 => 'Payment Required',
54
        403 => 'Forbidden',
55
        404 => 'Not Found',
56
        405 => 'Method Not Allowed',
57
        406 => 'Not Acceptable',
58
        407 => 'Proxy Authentication Required',
59
        408 => 'Request Timeout',
60
        409 => 'Conflict',
61
        410 => 'Gone',
62
        411 => 'Length Required',
63
        412 => 'Precondition Failed',
64
        413 => 'Payload Too Large',
65
        414 => 'URI Too Long',
66
        415 => 'Unsupported Media Type',
67
        416 => 'Range Not Satisfiable',
68
        417 => 'Expectation Failed',
69
        422 => 'Unprocessable Entity',                                        // RFC4918
70
        423 => 'Locked',                                                      // RFC4918
71
        424 => 'Failed Dependency',                                           // RFC4918
72
        425 => 'Reserved for WebDAV advanced collections expired proposal',   // RFC2817
73
        426 => 'Upgrade Required',                                            // RFC2817
74
        428 => 'Precondition Required',                                       // RFC6585
75
        429 => 'Too Many Requests',                                           // RFC6585
76
        431 => 'Request Header Fields Too Large',                             // RFC6585
77
        // Server Error 5xx
78
        500 => 'Internal Server Error',
79
        501 => 'Not Implemented',
80
        502 => 'Bad Gateway',
81
        503 => 'Service Unavailable',
82
        504 => 'Gateway Timeout',
83
        505 => 'HTTP Version Not Supported',
84
        506 => 'Variant Also Negotiates (Experimental)',                      // RFC2295
85
        507 => 'Insufficient Storage',                                        // RFC4918
86
        508 => 'Loop Detected',                                               // RFC5842
87
        510 => 'Not Extended',                                                // RFC2774
88
        511 => 'Network Authentication Required',                             // RFC6585
89
    ];
90
91
92
    /**
93
     * Default http status code
94
     */
95
    const DEFAULT_STATUS_CODE = 200;
96
97
    /**
98
     * Not Modified http status code
99
     */
100
    const NOT_MODIFIED_STATUS_CODE = 304;
101
102
    /**
103
     * Limits for tracked ids
104
     */
105
    const MAX_TRACKED_EVENTS = 200;
106
107
    /**
108
     * Url prefixes
109
     */
110
    const URL_PREFIX = 'https://api.telegram.org/bot';
111
112
    /**
113
     * Url prefix for files
114
     */
115
    const FILE_URL_PREFIX = 'https://api.telegram.org/file/bot';
116
117
    /**
118
     * CURL object
119
     *
120
     * @var
121
     */
122
    protected $curl;
123
124
    /**
125
     * Bot token
126
     *
127
     * @var string
128
     */
129
    protected $token;
130
131
    /**
132
     * Botan tracker
133
     *
134
     * @var \TelegramBot\Api\Botan
135
     */
136
    protected $tracker;
137
138
    /**
139
     * list of event ids
140
     *
141
     * @var array
142
     */
143
    protected $trackedEvents = [];
144
145
    /**
146
     * Check whether return associative array
147
     *
148
     * @var bool
149
     */
150
    protected $returnArray = true;
151
152
153
    /**
154
     * Constructor
155
     *
156
     * @param string $token Telegram Bot API token
157
     * @param string|null $trackerToken Yandex AppMetrica application api_key
158
     */
159 9
    public function __construct($token, $trackerToken = null)
160
    {
161 9
        $this->curl = curl_init();
162 9
        $this->token = $token;
163
164 9
        if ($trackerToken) {
165
            $this->tracker = new Botan($trackerToken);
166
        }
167 9
    }
168
169
    /**
170
     * Set return array
171
     *
172
     * @param bool $mode
173
     *
174
     * @return $this
175
     */
176
    public function setModeObject($mode = true)
177
    {
178
        $this->returnArray = !$mode;
179
180
        return $this;
181
    }
182
183
184
    /**
185
     * Call method
186
     *
187
     * @param string $method
188
     * @param array|null $data
189
     *
190
     * @return mixed
191
     * @throws \TelegramBot\Api\Exception
192
     * @throws \TelegramBot\Api\HttpException
193
     * @throws \TelegramBot\Api\InvalidJsonException
194
     */
195
    public function call($method, array $data = null)
196
    {
197
        $options = [
198
            CURLOPT_URL => $this->getUrl() . '/' . $method,
199
            CURLOPT_RETURNTRANSFER => true,
200
            CURLOPT_POST => null,
201
            CURLOPT_POSTFIELDS => null
202
        ];
203
204
        if ($data) {
205
            $options[CURLOPT_POST] = true;
206
            $options[CURLOPT_POSTFIELDS] = $data;
207
        }
208
209
        $response = self::jsonValidate($this->executeCurl($options), $this->returnArray);
210
211
        if ($this->returnArray) {
212
            if (!isset($response['ok'])) {
213
                throw new Exception($response['description'], $response['error_code']);
214
            }
215
216
            return $response['result'];
217
        }
218
219
        if (!$response->ok) {
220
            throw new Exception($response->description, $response->error_code);
221
        }
222
223
        return $response->result;
224
    }
225
226
    /**
227
     * curl_exec wrapper for response validation
228
     *
229
     * @param array $options
230
     *
231
     * @return string
232
     *
233
     * @throws \TelegramBot\Api\HttpException
234
     */
235
    protected function executeCurl(array $options)
236
    {
237
        curl_setopt_array($this->curl, $options);
238
239
        $result = curl_exec($this->curl);
240
        self::curlValidate($this->curl);
241
242
        return $result;
243
    }
244
245
    /**
246
     * Response validation
247
     *
248
     * @param resource $curl
249
     *
250
     * @throws \TelegramBot\Api\HttpException
251
     */
252
    public static function curlValidate($curl)
253
    {
254
        if (($httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE))
255
            && !in_array($httpCode, [self::DEFAULT_STATUS_CODE, self::NOT_MODIFIED_STATUS_CODE])
256
        ) {
257
            throw new HttpException(self::$codes[$httpCode], $httpCode);
258
        }
259
    }
260
261
    /**
262
     * JSON validation
263
     *
264
     * @param string $jsonString
265
     * @param boolean $asArray
266
     *
267
     * @return object|array
268
     * @throws \TelegramBot\Api\InvalidJsonException
269
     */
270
    public static function jsonValidate($jsonString, $asArray)
271
    {
272
        $json = json_decode($jsonString, $asArray);
273
274
        if (json_last_error() != JSON_ERROR_NONE) {
275
            throw new InvalidJsonException(json_last_error_msg(), json_last_error());
276
        }
277
278
        return $json;
279
    }
280
281
    /**
282
     * Use this method to send text messages. On success, the sent \TelegramBot\Api\Types\Message is returned.
283
     *
284
     * @param int|string $chatId
285
     * @param string $text
286
     * @param string|null $parseMode
287
     * @param bool $disablePreview
288
     * @param int|null $replyToMessageId
289
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
290
     * @param bool $disableNotification
291
     *
292
     * @return \TelegramBot\Api\Types\Message
293
     * @throws \TelegramBot\Api\InvalidArgumentException
294
     * @throws \TelegramBot\Api\Exception
295
     */
296
    public function sendMessage(
297
        $chatId,
298
        $text,
299
        $parseMode = null,
300
        $disablePreview = false,
301
        $replyToMessageId = null,
302
        $replyMarkup = null,
303
        $disableNotification = false
304
    ) {
305
        return Message::fromResponse($this->call('sendMessage', [
306
            'chat_id' => $chatId,
307
            'text' => $text,
308
            'parse_mode' => $parseMode,
309
            'disable_web_page_preview' => $disablePreview,
310
            'reply_to_message_id' => (int) $replyToMessageId,
311
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
312
            'disable_notification' => (bool) $disableNotification,
313
        ]));
314
    }
315
316
    /**
317
     * Use this method when you need to tell the user that something is happening on the bot's side.
318
     * The status is set for 5 seconds or less (when a message arrives from your bot,
319
     * Telegram clients clear its typing status).
320
     *
321
     * We only recommend using this method when a response from the bot will take a noticeable amount of time to arrive.
322
     *
323
     * Type of action to broadcast. Choose one, depending on what the user is about to receive:
324
     * `typing` for text messages, `upload_photo` for photos, `record_video` or `upload_video` for videos,
325
     * `record_audio` or upload_audio for audio files, `upload_document` for general files,
326
     * `find_location` for location data.
327
     *
328
     * @param int $chatId
329
     * @param string $action
330
     *
331
     * @return bool
332
     * @throws \TelegramBot\Api\Exception
333
     */
334
    public function sendChatAction($chatId, $action)
335
    {
336
        return $this->call('sendChatAction', [
337
            'chat_id' => $chatId,
338
            'action' => $action
339
        ]);
340
    }
341
342
    /**
343
     * Use this method to get a list of profile pictures for a user.
344
     *
345
     * @param int $userId
346
     * @param int $offset
347
     * @param int $limit
348
     *
349
     * @return \TelegramBot\Api\Types\UserProfilePhotos
350
     * @throws \TelegramBot\Api\Exception
351
     */
352
    public function getUserProfilePhotos($userId, $offset = 0, $limit = 100)
353
    {
354
        return UserProfilePhotos::fromResponse($this->call('getUserProfilePhotos', [
355
            'user_id' => (int) $userId,
356
            'offset' => (int) $offset,
357
            'limit' => (int) $limit,
358
        ]));
359
    }
360
361
    /**
362
     * Use this method to specify a url and receive incoming updates via an outgoing webhook.
363
     * Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url,
364
     * containing a JSON-serialized Update.
365
     * In case of an unsuccessful request, we will give up after a reasonable amount of attempts.
366
     *
367
     * @param string $url HTTPS url to send updates to. Use an empty string to remove webhook integration
368
     * @param \CURLFile|string $certificate Upload your public key certificate
369
     *                                      so that the root certificate in use can be checked
370
     *
371
     * @return string
372
     *
373
     * @throws \TelegramBot\Api\Exception
374
     */
375
    public function setWebhook($url = '', $certificate = null)
376
    {
377
        return $this->call('setWebhook', ['url' => $url, 'certificate' => $certificate]);
378
    }
379
380
    /**
381
     * A simple method for testing your bot's auth token.Requires no parameters.
382
     * Returns basic information about the bot in form of a User object.
383
     *
384
     * @return \TelegramBot\Api\Types\User
385
     * @throws \TelegramBot\Api\Exception
386
     * @throws \TelegramBot\Api\InvalidArgumentException
387
     */
388
    public function getMe()
389
    {
390
        return User::fromResponse($this->call('getMe'));
391
    }
392
393
    /**
394
     * Use this method to receive incoming updates using long polling.
395
     * An Array of Update objects is returned.
396
     *
397
     * Notes
398
     * 1. This method will not work if an outgoing webhook is set up.
399
     * 2. In order to avoid getting duplicate updates, recalculate offset after each server response.
400
     *
401
     * @param int $offset
402
     * @param int $limit
403
     * @param int $timeout
404
     *
405
     * @return Update[]
406
     * @throws \TelegramBot\Api\Exception
407
     * @throws \TelegramBot\Api\InvalidArgumentException
408
     */
409 2
    public function getUpdates($offset = 0, $limit = 100, $timeout = 0)
410
    {
411 2
        $updates = ArrayOfUpdates::fromResponse($this->call('getUpdates', [
412 2
            'offset' => $offset,
413 2
            'limit' => $limit,
414
            'timeout' => $timeout
415 2
        ]));
416
417 2
        if ($this->tracker instanceof Botan) {
418
            foreach ($updates as $update) {
419
                $this->trackUpdate($update);
420
            }
421
        }
422
423 2
        return $updates;
424
    }
425
426
    /**
427
     * Use this method to send point on the map. On success, the sent Message is returned.
428
     *
429
     * @param int $chatId
430
     * @param float $latitude
431
     * @param float $longitude
432
     * @param int|null $replyToMessageId
433
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
434
     * @param bool $disableNotification
435
     *
436
     * @return \TelegramBot\Api\Types\Message
437
     * @throws \TelegramBot\Api\Exception
438
     */
439 View Code Duplication
    public function sendLocation(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
440
        $chatId,
441
        $latitude,
442
        $longitude,
443
        $replyToMessageId = null,
444
        $replyMarkup = null,
445
        $disableNotification = false
446
    ) {
447
        return Message::fromResponse($this->call('sendLocation', [
448
            'chat_id' => $chatId,
449
            'latitude' => $latitude,
450
            'longitude' => $longitude,
451
            'reply_to_message_id' => $replyToMessageId,
452
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
453
            'disable_notification' => (bool) $disableNotification
454
        ]));
455
    }
456
457
    /**
458
     * Use this method to send .webp stickers. On success, the sent Message is returned.
459
     *
460
     * @param int $chatId
461
     * @param \CURLFile|string $sticker
462
     * @param int|null $replyToMessageId
463
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
464
     * @param bool $disableNotification
465
     *
466
     * @return \TelegramBot\Api\Types\Message
467
     * @throws \TelegramBot\Api\InvalidArgumentException
468
     * @throws \TelegramBot\Api\Exception
469
     */
470 View Code Duplication
    public function sendSticker(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
471
        $chatId,
472
        $sticker,
473
        $replyToMessageId = null,
474
        $replyMarkup = null,
475
        $disableNotification = false
476
    ) {
477
        return Message::fromResponse($this->call('sendSticker', [
478
            'chat_id' => $chatId,
479
            'sticker' => $sticker,
480
            'reply_to_message_id' => $replyToMessageId,
481
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
482
            'disable_notification' => (bool) $disableNotification
483
        ]));
484
    }
485
486
    /**
487
     * Use this method to send video files,
488
     * Telegram clients support mp4 videos (other formats may be sent as Document).
489
     * On success, the sent Message is returned.
490
     *
491
     * @param int $chatId
492
     * @param \CURLFile|string $video
493
     * @param int|null $duration
494
     * @param string|null $caption
495
     * @param int|null $replyToMessageId
496
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
497
     * @param bool $disableNotification
498
     *
499
     * @return \TelegramBot\Api\Types\Message
500
     * @throws \TelegramBot\Api\InvalidArgumentException
501
     * @throws \TelegramBot\Api\Exception
502
     */
503
    public function sendVideo(
504
        $chatId,
505
        $video,
506
        $duration = null,
507
        $caption = null,
508
        $replyToMessageId = null,
509
        $replyMarkup = null,
510
        $disableNotification = false
511
    ) {
512
        return Message::fromResponse($this->call('sendVideo', [
513
            'chat_id' => $chatId,
514
            'video' => $video,
515
            'duration' => $duration,
516
            'caption' => $caption,
517
            'reply_to_message_id' => $replyToMessageId,
518
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
519
            'disable_notification' => (bool) $disableNotification
520
        ]));
521
    }
522
523
    /**
524
     * Use this method to send audio files,
525
     * if you want Telegram clients to display the file as a playable voice message.
526
     * For this to work, your audio must be in an .ogg file encoded with OPUS
527
     * (other formats may be sent as Audio or Document).
528
     * On success, the sent Message is returned.
529
     * Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future.
530
     *
531
     * @param int $chatId
532
     * @param \CURLFile|string $voice
533
     * @param int|null $duration
534
     * @param int|null $replyToMessageId
535
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
536
     * @param bool $disableNotification
537
     *
538
     * @return \TelegramBot\Api\Types\Message
539
     * @throws \TelegramBot\Api\InvalidArgumentException
540
     * @throws \TelegramBot\Api\Exception
541
     */
542 View Code Duplication
    public function sendVoice(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
543
        $chatId,
544
        $voice,
545
        $duration = null,
546
        $replyToMessageId = null,
547
        $replyMarkup = null,
548
        $disableNotification = false
549
    ) {
550
        return Message::fromResponse($this->call('sendVoice', [
551
            'chat_id' => $chatId,
552
            'voice' => $voice,
553
            'duration' => $duration,
554
            'reply_to_message_id' => $replyToMessageId,
555
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
556
            'disable_notification' => (bool) $disableNotification
557
        ]));
558
    }
559
560
    /**
561
     * Use this method to forward messages of any kind. On success, the sent Message is returned.
562
     *
563
     * @param int $chatId
564
     * @param int $fromChatId
565
     * @param int $messageId
566
     * @param bool $disableNotification
567
     *
568
     * @return \TelegramBot\Api\Types\Message
569
     * @throws \TelegramBot\Api\InvalidArgumentException
570
     * @throws \TelegramBot\Api\Exception
571
     */
572
    public function forwardMessage($chatId, $fromChatId, $messageId, $disableNotification = false)
573
    {
574
        return Message::fromResponse($this->call('forwardMessage', [
575
            'chat_id' => $chatId,
576
            'from_chat_id' => $fromChatId,
577
            'message_id' => (int) $messageId,
578
            'disable_notification' => (bool) $disableNotification
579
        ]));
580
    }
581
582
    /**
583
     * Use this method to send audio files,
584
     * if you want Telegram clients to display them in the music player.
585
     * Your audio must be in the .mp3 format.
586
     * On success, the sent Message is returned.
587
     * Bots can currently send audio files of up to 50 MB in size, this limit may be changed in the future.
588
     *
589
     * For backward compatibility, when the fields title and performer are both empty
590
     * and the mime-type of the file to be sent is not audio/mpeg, the file will be sent as a playable voice message.
591
     * For this to work, the audio must be in an .ogg file encoded with OPUS.
592
     * This behavior will be phased out in the future. For sending voice messages, use the sendVoice method instead.
593
     *
594
     * @deprecated since 20th February. Removed backward compatibility from the method sendAudio.
595
     * Voice messages now must be sent using the method sendVoice.
596
     * There is no more need to specify a non-empty title or performer while sending the audio by file_id.
597
     *
598
     * @param int $chatId
599
     * @param \CURLFile|string $audio
600
     * @param int|null $duration
601
     * @param string|null $performer
602
     * @param string|null $title
603
     * @param int|null $replyToMessageId
604
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
605
     * @param bool $disableNotification
606
     *
607
     * @return \TelegramBot\Api\Types\Message
608
     * @throws \TelegramBot\Api\InvalidArgumentException
609
     * @throws \TelegramBot\Api\Exception
610
     */
611
    public function sendAudio(
612
        $chatId,
613
        $audio,
614
        $duration = null,
615
        $performer = null,
616
        $title = null,
617
        $replyToMessageId = null,
618
        $replyMarkup = null,
619
        $disableNotification = false
620
    ) {
621
        return Message::fromResponse($this->call('sendAudio', [
622
            'chat_id' => $chatId,
623
            'audio' => $audio,
624
            'duration' => $duration,
625
            'performer' => $performer,
626
            'title' => $title,
627
            'reply_to_message_id' => $replyToMessageId,
628
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
629
            'disable_notification' => (bool) $disableNotification
630
        ]));
631
    }
632
633
    /**
634
     * Use this method to send photos. On success, the sent Message is returned.
635
     *
636
     * @param int $chatId
637
     * @param \CURLFile|string $photo
638
     * @param string|null $caption
639
     * @param int|null $replyToMessageId
640
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
641
     * @param bool $disableNotification
642
     *
643
     * @return \TelegramBot\Api\Types\Message
644
     * @throws \TelegramBot\Api\InvalidArgumentException
645
     * @throws \TelegramBot\Api\Exception
646
     */
647 View Code Duplication
    public function sendPhoto(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
648
        $chatId,
649
        $photo,
650
        $caption = null,
651
        $replyToMessageId = null,
652
        $replyMarkup = null,
653
        $disableNotification = false
654
    ) {
655
        return Message::fromResponse($this->call('sendPhoto', [
656
            'chat_id' => $chatId,
657
            'photo' => $photo,
658
            'caption' => $caption,
659
            'reply_to_message_id' => $replyToMessageId,
660
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
661
            'disable_notification' => (bool) $disableNotification
662
        ]));
663
    }
664
665
    /**
666
     * Use this method to send general files. On success, the sent Message is returned.
667
     * Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future.
668
     *
669
     * @param int $chatId
670
     * @param \CURLFile|string $document
671
     * @param int|null $replyToMessageId
672
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
673
     * @param bool $disableNotification
674
     *
675
     * @return \TelegramBot\Api\Types\Message
676
     * @throws \TelegramBot\Api\InvalidArgumentException
677
     * @throws \TelegramBot\Api\Exception
678
     */
679 View Code Duplication
    public function sendDocument(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
680
        $chatId,
681
        $document,
682
        $replyToMessageId = null,
683
        $replyMarkup = null,
684
        $disableNotification = false
685
    ) {
686
        return Message::fromResponse($this->call('sendDocument', [
687
            'chat_id' => $chatId,
688
            'document' => $document,
689
            'reply_to_message_id' => $replyToMessageId,
690
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
691
            'disable_notification' => (bool) $disableNotification
692
        ]));
693
    }
694
695
    /**
696
     * Use this method to get basic info about a file and prepare it for downloading.
697
     * For the moment, bots can download files of up to 20MB in size.
698
     * On success, a File object is returned.
699
     * The file can then be downloaded via the link https://api.telegram.org/file/bot<token>/<file_path>,
700
     * where <file_path> is taken from the response.
701
     * It is guaranteed that the link will be valid for at least 1 hour.
702
     * When the link expires, a new one can be requested by calling getFile again.
703
     *
704
     * @param $fileId
705
     *
706
     * @return \TelegramBot\Api\Types\File
707
     * @throws \TelegramBot\Api\InvalidArgumentException
708
     * @throws \TelegramBot\Api\Exception
709
     */
710
    public function getFile($fileId)
711
    {
712
        return File::fromResponse($this->call('getFile', ['file_id' => $fileId]));
713
    }
714
715
    /**
716
     * Get file contents via cURL
717
     *
718
     * @param $fileId
719
     *
720
     * @return string
721
     *
722
     * @throws \TelegramBot\Api\HttpException
723
     */
724
    public function downloadFile($fileId)
725
    {
726
        $file = $this->getFile($fileId);
727
        $options = [
728
            CURLOPT_HEADER => 0,
729
            CURLOPT_HTTPGET => 1,
730
            CURLOPT_RETURNTRANSFER => 1,
731
            CURLOPT_URL => $this->getFileUrl() . '/' . $file->getFilePath()
732
        ];
733
734
        return $this->executeCurl($options);
735
    }
736
737
    /**
738
     * Use this method to send answers to an inline query. On success, True is returned.
739
     * No more than 50 results per query are allowed.
740
     *
741
     * @param string $inlineQueryId
742
     * @param \TelegramBot\Api\Types\Inline\AbstractInlineQueryResult[] $results
743
     * @param int $cacheTime
744
     * @param bool $isPersonal
745
     * @param string $nextOffset
746
     *
747
     * @return mixed
748
     * @throws Exception
749
     */
750
    public function answerInlineQuery($inlineQueryId, $results, $cacheTime = 300, $isPersonal = false, $nextOffset = '')
751
    {
752
        $results = array_map(function ($item) {
753
            /* @var \TelegramBot\Api\Types\Inline\AbstractInlineQueryResult $item */
754
755
            return json_decode($item->toJson(), true);
756
        }, $results);
757
758
        return $this->call('answerInlineQuery', [
759
            'inline_query_id' => $inlineQueryId,
760
            'results' => json_encode($results),
761
            'cache_time' => $cacheTime,
762
            'is_personal' => $isPersonal,
763
            'next_offset' => $nextOffset,
764
        ]);
765
    }
766
767
    /**
768
     * Use this method to kick a user from a group or a supergroup.
769
     * In the case of supergroups, the user will not be able to return to the group
770
     * on their own using invite links, etc., unless unbanned first.
771
     * The bot must be an administrator in the group for this to work. Returns True on success.
772
     *
773
     * @param int|string $chatId Unique identifier for the target group
774
     * or username of the target supergroup (in the format @supergroupusername)
775
     * @param int $userId Unique identifier of the target user
776
     *
777
     * @return bool
778
     */
779
    public function kickChatMember($chatId, $userId)
780
    {
781
        return $this->call('kickChatMember', [
782
            'chat_id' => $chatId,
783
            'user_id' => $userId,
784
        ]);
785
    }
786
787
    /**
788
     * Use this method to unban a previously kicked user in a supergroup.
789
     * The user will not return to the group automatically, but will be able to join via link, etc.
790
     * The bot must be an administrator in the group for this to work. Returns True on success.
791
     *
792
     * @param int|string $chatId Unique identifier for the target group
793
     * or username of the target supergroup (in the format @supergroupusername)
794
     * @param int $userId Unique identifier of the target user
795
     *
796
     * @return bool
797
     */
798
    public function unbanChatMember($chatId, $userId) {
799
        return $this->call('unbanChatMember', [
800
            'chat_id' => $chatId,
801
            'user_id' => $userId
802
        ]);
803
    }
804
805
    /**
806
     * Use this method to send answers to callback queries sent from inline keyboards.
807
     * The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.
808
     *
809
     * @param $callbackQueryId
810
     * @param null $text
811
     * @param bool $showAlert
812
     *
813
     * @return bool
814
     */
815
    public function answerCallbackQuery($callbackQueryId, $text = null, $showAlert = false)
816
    {
817
        return $this->call('answerCallbackQuery', [
818
            'callback_query_id' => $callbackQueryId,
819
            'text' => $text,
820
            'show_alert' => (bool)$showAlert,
821
        ]);
822
    }
823
824
825
    /**
826
     * Use this method to edit text messages sent by the bot or via the bot (for inline bots)
827
     *
828
     * @param int|string $chatId
829
     * @param int $messageId
830
     * @param string $text
831
     * @param string|null $parseMode
832
     * @param bool $disablePreview
833
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
834
     *
835
     * @return \TelegramBot\Api\Types\Message
836
     * @throws \TelegramBot\Api\InvalidArgumentException
837
     * @throws \TelegramBot\Api\Exception
838
     */
839 View Code Duplication
    public function editMessageText(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
840
        $chatId,
841
        $messageId,
842
        $text,
843
        $parseMode = null,
844
        $disablePreview = false,
845
        $replyMarkup = null
846
    ) {
847
        return Message::fromResponse($this->call('editMessageText', [
848
            'chat_id' => $chatId,
849
            'message_id' => $messageId,
850
            'text' => $text,
851
            'parse_mode' => $parseMode,
852
            'disable_web_page_preview' => $disablePreview,
853
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
854
        ]));
855
    }
856
857
    /**
858
     * Use this method to edit text messages sent by the bot or via the bot
859
     *
860
     * @param int|string $chatId
861
     * @param int $messageId
862
     * @param string|null $caption
863
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
864
     *
865
     * @return \TelegramBot\Api\Types\Message
866
     * @throws \TelegramBot\Api\InvalidArgumentException
867
     * @throws \TelegramBot\Api\Exception
868
     */
869 View Code Duplication
    public function editMessageCaption(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
870
        $chatId,
871
        $messageId,
872
        $caption = null,
873
        $replyMarkup = null
874
    ) {
875
        return Message::fromResponse($this->call('editMessageText', [
876
            'chat_id' => $chatId,
877
            'message_id' => $messageId,
878
            'caption' => $caption,
879
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
880
        ]));
881
    }
882
883
    /**
884
     * Use this method to edit only the reply markup of messages sent by the bot or via the bot
885
     *
886
     * @param int|string $chatId
887
     * @param int $messageId
888
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
889
     *
890
     * @return \TelegramBot\Api\Types\Message
891
     * @throws \TelegramBot\Api\InvalidArgumentException
892
     * @throws \TelegramBot\Api\Exception
893
     */
894 View Code Duplication
    public function editMessageReplyMarkup(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
895
        $chatId,
896
        $messageId,
897
        $replyMarkup = null
898
    ) {
899
        return Message::fromResponse($this->call('editMessageText', [
900
            'chat_id' => $chatId,
901
            'message_id' => $messageId,
902
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
903
        ]));
904
    }
905
906
    /**
907
     * Close curl
908
     */
909 9
    public function __destruct()
910
    {
911 9
        $this->curl && curl_close($this->curl);
912 9
    }
913
914
    /**
915
     * @return string
916
     */
917
    public function getUrl()
918
    {
919
        return self::URL_PREFIX . $this->token;
920
    }
921
922
    /**
923
     * @return string
924
     */
925
    public function getFileUrl()
926
    {
927
        return self::FILE_URL_PREFIX . $this->token;
928
    }
929
930
    /**
931
     * @param \TelegramBot\Api\Types\Update $update
932
     * @param string $eventName
933
     *
934
     * @throws \TelegramBot\Api\Exception
935
     */
936
    public function trackUpdate(Update $update, $eventName = 'Message')
937
    {
938
        if (!in_array($update->getUpdateId(), $this->trackedEvents)) {
939
            $this->trackedEvents[] = $update->getUpdateId();
940
941
            $this->track($update->getMessage(), $eventName);
942
943
            if (count($this->trackedEvents) > self::MAX_TRACKED_EVENTS) {
944
                $this->trackedEvents = array_slice($this->trackedEvents, round(self::MAX_TRACKED_EVENTS / 4));
945
            }
946
        }
947
    }
948
949
    /**
950
     * Wrapper for tracker
951
     *
952
     * @param \TelegramBot\Api\Types\Message $message
953
     * @param string $eventName
954
     *
955
     * @throws \TelegramBot\Api\Exception
956
     */
957
    public function track(Message $message, $eventName = 'Message')
958
    {
959
        if ($this->tracker instanceof Botan) {
960
            $this->tracker->track($message, $eventName);
961
        }
962
    }
963
}
964