Completed
Push — master ( 0d01f6...5f8f6d )
by Gusev
03:03
created

BotApi::sendMessage()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 19
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 5
Bugs 2 Features 1
Metric Value
c 5
b 2
f 1
dl 0
loc 19
ccs 0
cts 10
cp 0
rs 9.4285
cc 2
eloc 16
nc 1
nop 7
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\Inline\QueryResult\AbstractInlineQueryResult;
8
use TelegramBot\Api\Types\Message;
9
use TelegramBot\Api\Types\Update;
10
use TelegramBot\Api\Types\User;
11
use TelegramBot\Api\Types\UserProfilePhotos;
12
13
/**
14
 * Class BotApi
15
 *
16
 * @package TelegramBot\Api
17
 */
18
class BotApi
19
{
20
    /**
21
     * HTTP codes
22
     *
23
     * @var array
24
     */
25
    public static $codes = [
26
        // Informational 1xx
27
        100 => 'Continue',
28
        101 => 'Switching Protocols',
29
        102 => 'Processing',            // RFC2518
30
        // Success 2xx
31
        200 => 'OK',
32
        201 => 'Created',
33
        202 => 'Accepted',
34
        203 => 'Non-Authoritative Information',
35
        204 => 'No Content',
36
        205 => 'Reset Content',
37
        206 => 'Partial Content',
38
        207 => 'Multi-Status',          // RFC4918
39
        208 => 'Already Reported',      // RFC5842
40
        226 => 'IM Used',               // RFC3229
41
        // Redirection 3xx
42
        300 => 'Multiple Choices',
43
        301 => 'Moved Permanently',
44
        302 => 'Found', // 1.1
45
        303 => 'See Other',
46
        304 => 'Not Modified',
47
        305 => 'Use Proxy',
48
        // 306 is deprecated but reserved
49
        307 => 'Temporary Redirect',
50
        308 => 'Permanent Redirect',    // RFC7238
51
        // Client Error 4xx
52
        400 => 'Bad Request',
53
        401 => 'Unauthorized',
54
        402 => 'Payment Required',
55
        403 => 'Forbidden',
56
        404 => 'Not Found',
57
        405 => 'Method Not Allowed',
58
        406 => 'Not Acceptable',
59
        407 => 'Proxy Authentication Required',
60
        408 => 'Request Timeout',
61
        409 => 'Conflict',
62
        410 => 'Gone',
63
        411 => 'Length Required',
64
        412 => 'Precondition Failed',
65
        413 => 'Payload Too Large',
66
        414 => 'URI Too Long',
67
        415 => 'Unsupported Media Type',
68
        416 => 'Range Not Satisfiable',
69
        417 => 'Expectation Failed',
70
        422 => 'Unprocessable Entity',                                        // RFC4918
71
        423 => 'Locked',                                                      // RFC4918
72
        424 => 'Failed Dependency',                                           // RFC4918
73
        425 => 'Reserved for WebDAV advanced collections expired proposal',   // RFC2817
74
        426 => 'Upgrade Required',                                            // RFC2817
75
        428 => 'Precondition Required',                                       // RFC6585
76
        429 => 'Too Many Requests',                                           // RFC6585
77
        431 => 'Request Header Fields Too Large',                             // RFC6585
78
        // Server Error 5xx
79
        500 => 'Internal Server Error',
80
        501 => 'Not Implemented',
81
        502 => 'Bad Gateway',
82
        503 => 'Service Unavailable',
83
        504 => 'Gateway Timeout',
84
        505 => 'HTTP Version Not Supported',
85
        506 => 'Variant Also Negotiates (Experimental)',                      // RFC2295
86
        507 => 'Insufficient Storage',                                        // RFC4918
87
        508 => 'Loop Detected',                                               // RFC5842
88
        510 => 'Not Extended',                                                // RFC2774
89
        511 => 'Network Authentication Required',                             // RFC6585
90
    ];
91
92
93
    /**
94
     * Default http status code
95
     */
96
    const DEFAULT_STATUS_CODE = 200;
97
98
    /**
99
     * Not Modified http status code
100
     */
101
    const NOT_MODIFIED_STATUS_CODE = 304;
102
103
    /**
104
     * Limits for tracked ids
105
     */
106
    const MAX_TRACKED_EVENTS = 200;
107
108
    /**
109
     * Url prefixes
110
     */
111
    const URL_PREFIX = 'https://api.telegram.org/bot';
112
113
    /**
114
     * Url prefix for files
115
     */
116
    const FILE_URL_PREFIX = 'https://api.telegram.org/file/bot';
117
118
    /**
119
     * CURL object
120
     *
121
     * @var
122
     */
123
    protected $curl;
124
125
    /**
126
     * Bot token
127
     *
128
     * @var string
129
     */
130
    protected $token;
131
132
    /**
133
     * Botan tracker
134
     *
135
     * @var \TelegramBot\Api\Botan
136
     */
137
    protected $tracker;
138
139
    /**
140
     * list of event ids
141
     *
142
     * @var array
143
     */
144
    protected $trackedEvents = [];
145
146
    /**
147
     * Check whether return associative array
148
     *
149
     * @var bool
150
     */
151
    protected $returnArray = true;
152
153
154
    /**
155
     * Constructor
156
     *
157
     * @param string $token Telegram Bot API token
158
     * @param string|null $trackerToken Yandex AppMetrica application api_key
159
     */
160 9
    public function __construct($token, $trackerToken = null)
161
    {
162 9
        $this->curl = curl_init();
163 9
        $this->token = $token;
164
165 9
        if ($trackerToken) {
166
            $this->tracker = new Botan($trackerToken);
167
        }
168 9
    }
169
170
    /**
171
     * Set return array
172
     *
173
     * @param bool $mode
174
     *
175
     * @return $this
176
     */
177
    public function setModeObject($mode = true)
178
    {
179
        $this->returnArray = !$mode;
180
181
        return $this;
182
    }
183
184
185
    /**
186
     * Call method
187
     *
188
     * @param string $method
189
     * @param array|null $data
190
     *
191
     * @return mixed
192
     * @throws \TelegramBot\Api\Exception
193
     * @throws \TelegramBot\Api\HttpException
194
     * @throws \TelegramBot\Api\InvalidJsonException
195
     */
196
    public function call($method, array $data = null)
197
    {
198
        $options = [
199
            CURLOPT_URL => $this->getUrl().'/'.$method,
200
            CURLOPT_RETURNTRANSFER => true,
201
            CURLOPT_POST => null,
202
            CURLOPT_POSTFIELDS => null,
203
        ];
204
205
        if ($data) {
206
            $options[CURLOPT_POST] = true;
207
            $options[CURLOPT_POSTFIELDS] = $data;
208
        }
209
210
        $response = self::jsonValidate($this->executeCurl($options), $this->returnArray);
211
212
        if ($this->returnArray) {
213
            if (!isset($response['ok'])) {
214
                throw new Exception($response['description'], $response['error_code']);
215
            }
216
217
            return $response['result'];
218
        }
219
220
        if (!$response->ok) {
221
            throw new Exception($response->description, $response->error_code);
222
        }
223
224
        return $response->result;
225
    }
226
227
    /**
228
     * curl_exec wrapper for response validation
229
     *
230
     * @param array $options
231
     *
232
     * @return string
233
     *
234
     * @throws \TelegramBot\Api\HttpException
235
     */
236
    protected function executeCurl(array $options)
237
    {
238
        curl_setopt_array($this->curl, $options);
239
240
        $result = curl_exec($this->curl);
241
        self::curlValidate($this->curl);
242
243
        return $result;
244
    }
245
246
    /**
247
     * Response validation
248
     *
249
     * @param resource $curl
250
     *
251
     * @throws \TelegramBot\Api\HttpException
252
     */
253
    public static function curlValidate($curl)
254
    {
255
        if (($httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE))
256
            && !in_array($httpCode, [self::DEFAULT_STATUS_CODE, self::NOT_MODIFIED_STATUS_CODE])
257
        ) {
258
            throw new HttpException(self::$codes[$httpCode], $httpCode);
259
        }
260
    }
261
262
    /**
263
     * JSON validation
264
     *
265
     * @param string $jsonString
266
     * @param boolean $asArray
267
     *
268
     * @return object|array
269
     * @throws \TelegramBot\Api\InvalidJsonException
270
     */
271
    public static function jsonValidate($jsonString, $asArray)
272
    {
273
        $json = json_decode($jsonString, $asArray);
274
275
        if (json_last_error() != JSON_ERROR_NONE) {
276
            throw new InvalidJsonException(json_last_error_msg(), json_last_error());
277
        }
278
279
        return $json;
280
    }
281
282
    /**
283
     * Use this method to send text messages. On success, the sent \TelegramBot\Api\Types\Message is returned.
284
     *
285
     * @param int|string $chatId
286
     * @param string $text
287
     * @param string|null $parseMode
288
     * @param bool $disablePreview
289
     * @param int|null $replyToMessageId
290
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
291
     * @param bool $disableNotification
292
     *
293
     * @return \TelegramBot\Api\Types\Message
294
     * @throws \TelegramBot\Api\InvalidArgumentException
295
     * @throws \TelegramBot\Api\Exception
296
     */
297
    public function sendMessage(
298
        $chatId,
299
        $text,
300
        $parseMode = null,
301
        $disablePreview = false,
302
        $replyToMessageId = null,
303
        $replyMarkup = null,
304
        $disableNotification = false
305
    ) {
306
        return Message::fromResponse($this->call('sendMessage', [
307
            'chat_id' => $chatId,
308
            'text' => $text,
309
            'parse_mode' => $parseMode,
310
            'disable_web_page_preview' => $disablePreview,
311
            'reply_to_message_id' => (int)$replyToMessageId,
312
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
313
            'disable_notification' => (bool)$disableNotification,
314
        ]));
315
    }
316
317
    /**
318
     * Use this method to send phone contacts
319
     *
320
     * @param int $chatId
321
     * @param string $phoneNumber
322
     * @param string $firstName
323
     * @param string $lastName
324
     * @param int|null $replyToMessageId
325
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
326
     * @param bool $disableNotification
327
     *
328
     * @return \TelegramBot\Api\Types\Message
329
     * @throws \TelegramBot\Api\Exception
330
     */
331 View Code Duplication
    public function sendContact(
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...
332
        $chatId,
333
        $phoneNumber,
334
        $firstName,
335
        $lastName = null,
336
        $replyToMessageId = null,
337
        $replyMarkup = null,
338
        $disableNotification = false
339
    ) {
340
        return Message::fromResponse($this->call('sendContact', [
341
            'chat_id' => $chatId,
342
            'phone_number' => $phoneNumber,
343
            'first_name' => $firstName,
344
            'last_name' => $lastName,
345
            'reply_to_message_id' => $replyToMessageId,
346
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
347
            'disable_notification' => (bool)$disableNotification,
348
        ]));
349
    }
350
351
    /**
352
     * Use this method when you need to tell the user that something is happening on the bot's side.
353
     * The status is set for 5 seconds or less (when a message arrives from your bot,
354
     * Telegram clients clear its typing status).
355
     *
356
     * We only recommend using this method when a response from the bot will take a noticeable amount of time to arrive.
357
     *
358
     * Type of action to broadcast. Choose one, depending on what the user is about to receive:
359
     * `typing` for text messages, `upload_photo` for photos, `record_video` or `upload_video` for videos,
360
     * `record_audio` or upload_audio for audio files, `upload_document` for general files,
361
     * `find_location` for location data.
362
     *
363
     * @param int $chatId
364
     * @param string $action
365
     *
366
     * @return bool
367
     * @throws \TelegramBot\Api\Exception
368
     */
369
    public function sendChatAction($chatId, $action)
370
    {
371
        return $this->call('sendChatAction', [
372
            'chat_id' => $chatId,
373
            'action' => $action,
374
        ]);
375
    }
376
377
    /**
378
     * Use this method to get a list of profile pictures for a user.
379
     *
380
     * @param int $userId
381
     * @param int $offset
382
     * @param int $limit
383
     *
384
     * @return \TelegramBot\Api\Types\UserProfilePhotos
385
     * @throws \TelegramBot\Api\Exception
386
     */
387
    public function getUserProfilePhotos($userId, $offset = 0, $limit = 100)
388
    {
389
        return UserProfilePhotos::fromResponse($this->call('getUserProfilePhotos', [
390
            'user_id' => (int)$userId,
391
            'offset' => (int)$offset,
392
            'limit' => (int)$limit,
393
        ]));
394
    }
395
396
    /**
397
     * Use this method to specify a url and receive incoming updates via an outgoing webhook.
398
     * Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url,
399
     * containing a JSON-serialized Update.
400
     * In case of an unsuccessful request, we will give up after a reasonable amount of attempts.
401
     *
402
     * @param string $url HTTPS url to send updates to. Use an empty string to remove webhook integration
403
     * @param \CURLFile|string $certificate Upload your public key certificate
404
     *                                      so that the root certificate in use can be checked
405
     *
406
     * @return string
407
     *
408
     * @throws \TelegramBot\Api\Exception
409
     */
410
    public function setWebhook($url = '', $certificate = null)
411
    {
412
        return $this->call('setWebhook', ['url' => $url, 'certificate' => $certificate]);
413
    }
414
415
    /**
416
     * A simple method for testing your bot's auth token.Requires no parameters.
417
     * Returns basic information about the bot in form of a User object.
418
     *
419
     * @return \TelegramBot\Api\Types\User
420
     * @throws \TelegramBot\Api\Exception
421
     * @throws \TelegramBot\Api\InvalidArgumentException
422
     */
423
    public function getMe()
424
    {
425
        return User::fromResponse($this->call('getMe'));
426
    }
427
428
    /**
429
     * Use this method to receive incoming updates using long polling.
430
     * An Array of Update objects is returned.
431
     *
432
     * Notes
433
     * 1. This method will not work if an outgoing webhook is set up.
434
     * 2. In order to avoid getting duplicate updates, recalculate offset after each server response.
435
     *
436
     * @param int $offset
437
     * @param int $limit
438
     * @param int $timeout
439
     *
440
     * @return Update[]
441
     * @throws \TelegramBot\Api\Exception
442
     * @throws \TelegramBot\Api\InvalidArgumentException
443
     */
444 2
    public function getUpdates($offset = 0, $limit = 100, $timeout = 0)
445
    {
446 2
        $updates = ArrayOfUpdates::fromResponse($this->call('getUpdates', [
447 2
            'offset' => $offset,
448 2
            'limit' => $limit,
449 2
            'timeout' => $timeout,
450 2
        ]));
451
452 2
        if ($this->tracker instanceof Botan) {
453
            foreach ($updates as $update) {
454
                $this->trackUpdate($update);
455
            }
456
        }
457
458 2
        return $updates;
459
    }
460
461
    /**
462
     * Use this method to send point on the map. On success, the sent Message is returned.
463
     *
464
     * @param int $chatId
465
     * @param float $latitude
466
     * @param float $longitude
467
     * @param int|null $replyToMessageId
468
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
469
     * @param bool $disableNotification
470
     *
471
     * @return \TelegramBot\Api\Types\Message
472
     * @throws \TelegramBot\Api\Exception
473
     */
474 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...
475
        $chatId,
476
        $latitude,
477
        $longitude,
478
        $replyToMessageId = null,
479
        $replyMarkup = null,
480
        $disableNotification = false
481
    ) {
482
        return Message::fromResponse($this->call('sendLocation', [
483
            'chat_id' => $chatId,
484
            'latitude' => $latitude,
485
            'longitude' => $longitude,
486
            'reply_to_message_id' => $replyToMessageId,
487
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
488
            'disable_notification' => (bool)$disableNotification,
489
        ]));
490
    }
491
492
    /**
493
     * Use this method to send information about a venue. On success, the sent Message is returned.
494
     *
495
     * @param int|string $chatId
496
     * @param float $latitude
497
     * @param float $longitude
498
     * @param string $title
499
     * @param string $address
500
     * @param string|null $foursquareId
501
     * @param int|null $replyToMessageId
502
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
503
     * @param bool $disableNotification
504
     *
505
     * @return \TelegramBot\Api\Types\Message
506
     * @throws \TelegramBot\Api\Exception
507
     */
508
    public function sendVenue(
509
        $chatId,
510
        $latitude,
511
        $longitude,
512
        $title,
513
        $address,
514
        $foursquareId = null,
515
        $replyToMessageId = null,
516
        $replyMarkup = null,
517
        $disableNotification = false
518
    ) {
519
        return Message::fromResponse($this->call('sendVenue', [
520
            'chat_id' => $chatId,
521
            'latitude' => $latitude,
522
            'longitude' => $longitude,
523
            'title' => $title,
524
            'address' => $address,
525
            'foursquare_id' => $foursquareId,
526
            'reply_to_message_id' => $replyToMessageId,
527
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
528
            'disable_notification' => (bool)$disableNotification,
529
        ]));
530
    }
531
532
    /**
533
     * Use this method to send .webp stickers. On success, the sent Message is returned.
534
     *
535
     * @param int $chatId
536
     * @param \CURLFile|string $sticker
537
     * @param int|null $replyToMessageId
538
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
539
     * @param bool $disableNotification
540
     *
541
     * @return \TelegramBot\Api\Types\Message
542
     * @throws \TelegramBot\Api\InvalidArgumentException
543
     * @throws \TelegramBot\Api\Exception
544
     */
545 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...
546
        $chatId,
547
        $sticker,
548
        $replyToMessageId = null,
549
        $replyMarkup = null,
550
        $disableNotification = false
551
    ) {
552
        return Message::fromResponse($this->call('sendSticker', [
553
            'chat_id' => $chatId,
554
            'sticker' => $sticker,
555
            'reply_to_message_id' => $replyToMessageId,
556
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
557
            'disable_notification' => (bool)$disableNotification,
558
        ]));
559
    }
560
561
    /**
562
     * Use this method to send video files,
563
     * Telegram clients support mp4 videos (other formats may be sent as Document).
564
     * On success, the sent Message is returned.
565
     *
566
     * @param int $chatId
567
     * @param \CURLFile|string $video
568
     * @param int|null $duration
569
     * @param string|null $caption
570
     * @param int|null $replyToMessageId
571
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
572
     * @param bool $disableNotification
573
     *
574
     * @return \TelegramBot\Api\Types\Message
575
     * @throws \TelegramBot\Api\InvalidArgumentException
576
     * @throws \TelegramBot\Api\Exception
577
     */
578
    public function sendVideo(
579
        $chatId,
580
        $video,
581
        $duration = null,
582
        $caption = null,
583
        $replyToMessageId = null,
584
        $replyMarkup = null,
585
        $disableNotification = false
586
    ) {
587
        return Message::fromResponse($this->call('sendVideo', [
588
            'chat_id' => $chatId,
589
            'video' => $video,
590
            'duration' => $duration,
591
            'caption' => $caption,
592
            'reply_to_message_id' => $replyToMessageId,
593
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
594
            'disable_notification' => (bool)$disableNotification,
595
        ]));
596
    }
597
598
    /**
599
     * Use this method to send audio files,
600
     * if you want Telegram clients to display the file as a playable voice message.
601
     * For this to work, your audio must be in an .ogg file encoded with OPUS
602
     * (other formats may be sent as Audio or Document).
603
     * On success, the sent Message is returned.
604
     * Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future.
605
     *
606
     * @param int $chatId
607
     * @param \CURLFile|string $voice
608
     * @param int|null $duration
609
     * @param int|null $replyToMessageId
610
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
611
     * @param bool $disableNotification
612
     *
613
     * @return \TelegramBot\Api\Types\Message
614
     * @throws \TelegramBot\Api\InvalidArgumentException
615
     * @throws \TelegramBot\Api\Exception
616
     */
617 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...
618
        $chatId,
619
        $voice,
620
        $duration = null,
621
        $replyToMessageId = null,
622
        $replyMarkup = null,
623
        $disableNotification = false
624
    ) {
625
        return Message::fromResponse($this->call('sendVoice', [
626
            'chat_id' => $chatId,
627
            'voice' => $voice,
628
            'duration' => $duration,
629
            'reply_to_message_id' => $replyToMessageId,
630
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
631
            'disable_notification' => (bool)$disableNotification,
632
        ]));
633
    }
634
635
    /**
636
     * Use this method to forward messages of any kind. On success, the sent Message is returned.
637
     *
638
     * @param int $chatId
639
     * @param int $fromChatId
640
     * @param int $messageId
641
     * @param bool $disableNotification
642
     *
643
     * @return \TelegramBot\Api\Types\Message
644
     * @throws \TelegramBot\Api\InvalidArgumentException
645
     * @throws \TelegramBot\Api\Exception
646
     */
647
    public function forwardMessage($chatId, $fromChatId, $messageId, $disableNotification = false)
648
    {
649
        return Message::fromResponse($this->call('forwardMessage', [
650
            'chat_id' => $chatId,
651
            'from_chat_id' => $fromChatId,
652
            'message_id' => (int)$messageId,
653
            'disable_notification' => (bool)$disableNotification,
654
        ]));
655
    }
656
657
    /**
658
     * Use this method to send audio files,
659
     * if you want Telegram clients to display them in the music player.
660
     * Your audio must be in the .mp3 format.
661
     * On success, the sent Message is returned.
662
     * Bots can currently send audio files of up to 50 MB in size, this limit may be changed in the future.
663
     *
664
     * For backward compatibility, when the fields title and performer are both empty
665
     * and the mime-type of the file to be sent is not audio/mpeg, the file will be sent as a playable voice message.
666
     * For this to work, the audio must be in an .ogg file encoded with OPUS.
667
     * This behavior will be phased out in the future. For sending voice messages, use the sendVoice method instead.
668
     *
669
     * @deprecated since 20th February. Removed backward compatibility from the method sendAudio.
670
     * Voice messages now must be sent using the method sendVoice.
671
     * There is no more need to specify a non-empty title or performer while sending the audio by file_id.
672
     *
673
     * @param int $chatId
674
     * @param \CURLFile|string $audio
675
     * @param int|null $duration
676
     * @param string|null $performer
677
     * @param string|null $title
678
     * @param int|null $replyToMessageId
679
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
680
     * @param bool $disableNotification
681
     *
682
     * @return \TelegramBot\Api\Types\Message
683
     * @throws \TelegramBot\Api\InvalidArgumentException
684
     * @throws \TelegramBot\Api\Exception
685
     */
686
    public function sendAudio(
687
        $chatId,
688
        $audio,
689
        $duration = null,
690
        $performer = null,
691
        $title = null,
692
        $replyToMessageId = null,
693
        $replyMarkup = null,
694
        $disableNotification = false
695
    ) {
696
        return Message::fromResponse($this->call('sendAudio', [
697
            'chat_id' => $chatId,
698
            'audio' => $audio,
699
            'duration' => $duration,
700
            'performer' => $performer,
701
            'title' => $title,
702
            'reply_to_message_id' => $replyToMessageId,
703
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
704
            'disable_notification' => (bool)$disableNotification,
705
        ]));
706
    }
707
708
    /**
709
     * Use this method to send photos. On success, the sent Message is returned.
710
     *
711
     * @param int $chatId
712
     * @param \CURLFile|string $photo
713
     * @param string|null $caption
714
     * @param int|null $replyToMessageId
715
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
716
     * @param bool $disableNotification
717
     *
718
     * @return \TelegramBot\Api\Types\Message
719
     * @throws \TelegramBot\Api\InvalidArgumentException
720
     * @throws \TelegramBot\Api\Exception
721
     */
722 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...
723
        $chatId,
724
        $photo,
725
        $caption = null,
726
        $replyToMessageId = null,
727
        $replyMarkup = null,
728
        $disableNotification = false
729
    ) {
730
        return Message::fromResponse($this->call('sendPhoto', [
731
            'chat_id' => $chatId,
732
            'photo' => $photo,
733
            'caption' => $caption,
734
            'reply_to_message_id' => $replyToMessageId,
735
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
736
            'disable_notification' => (bool)$disableNotification,
737
        ]));
738
    }
739
740
    /**
741
     * Use this method to send general files. On success, the sent Message is returned.
742
     * Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future.
743
     *
744
     * @param int $chatId
745
     * @param \CURLFile|string $document
746
     * @param int|null $replyToMessageId
747
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
748
     * @param bool $disableNotification
749
     *
750
     * @return \TelegramBot\Api\Types\Message
751
     * @throws \TelegramBot\Api\InvalidArgumentException
752
     * @throws \TelegramBot\Api\Exception
753
     */
754 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...
755
        $chatId,
756
        $document,
757
        $replyToMessageId = null,
758
        $replyMarkup = null,
759
        $disableNotification = false
760
    ) {
761
        return Message::fromResponse($this->call('sendDocument', [
762
            'chat_id' => $chatId,
763
            'document' => $document,
764
            'reply_to_message_id' => $replyToMessageId,
765
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
766
            'disable_notification' => (bool)$disableNotification,
767
        ]));
768
    }
769
770
    /**
771
     * Use this method to get basic info about a file and prepare it for downloading.
772
     * For the moment, bots can download files of up to 20MB in size.
773
     * On success, a File object is returned.
774
     * The file can then be downloaded via the link https://api.telegram.org/file/bot<token>/<file_path>,
775
     * where <file_path> is taken from the response.
776
     * It is guaranteed that the link will be valid for at least 1 hour.
777
     * When the link expires, a new one can be requested by calling getFile again.
778
     *
779
     * @param $fileId
780
     *
781
     * @return \TelegramBot\Api\Types\File
782
     * @throws \TelegramBot\Api\InvalidArgumentException
783
     * @throws \TelegramBot\Api\Exception
784
     */
785
    public function getFile($fileId)
786
    {
787
        return File::fromResponse($this->call('getFile', ['file_id' => $fileId]));
788
    }
789
790
    /**
791
     * Get file contents via cURL
792
     *
793
     * @param $fileId
794
     *
795
     * @return string
796
     *
797
     * @throws \TelegramBot\Api\HttpException
798
     */
799
    public function downloadFile($fileId)
800
    {
801
        $file = $this->getFile($fileId);
802
        $options = [
803
            CURLOPT_HEADER => 0,
804
            CURLOPT_HTTPGET => 1,
805
            CURLOPT_RETURNTRANSFER => 1,
806
            CURLOPT_URL => $this->getFileUrl().'/'.$file->getFilePath(),
807
        ];
808
809
        return $this->executeCurl($options);
810
    }
811
812
    /**
813
     * Use this method to send answers to an inline query. On success, True is returned.
814
     * No more than 50 results per query are allowed.
815
     *
816
     * @param string $inlineQueryId
817
     * @param AbstractInlineQueryResult[] $results
818
     * @param int $cacheTime
819
     * @param bool $isPersonal
820
     * @param string $nextOffset
821
     *
822
     * @return mixed
823
     * @throws Exception
824
     */
825
    public function answerInlineQuery($inlineQueryId, $results, $cacheTime = 300, $isPersonal = false, $nextOffset = '')
826
    {
827
        $results = array_map(function ($item) {
828
            /* @var AbstractInlineQueryResult $item */
829
830
            return json_decode($item->toJson(), true);
831
        }, $results);
832
833
        return $this->call('answerInlineQuery', [
834
            'inline_query_id' => $inlineQueryId,
835
            'results' => json_encode($results),
836
            'cache_time' => $cacheTime,
837
            'is_personal' => $isPersonal,
838
            'next_offset' => $nextOffset,
839
        ]);
840
    }
841
842
    /**
843
     * Use this method to kick a user from a group or a supergroup.
844
     * In the case of supergroups, the user will not be able to return to the group
845
     * on their own using invite links, etc., unless unbanned first.
846
     * The bot must be an administrator in the group for this to work. Returns True on success.
847
     *
848
     * @param int|string $chatId Unique identifier for the target group
849
     * or username of the target supergroup (in the format @supergroupusername)
850
     * @param int $userId Unique identifier of the target user
851
     *
852
     * @return bool
853
     */
854
    public function kickChatMember($chatId, $userId)
855
    {
856
        return $this->call('kickChatMember', [
857
            'chat_id' => $chatId,
858
            'user_id' => $userId,
859
        ]);
860
    }
861
862
    /**
863
     * Use this method to unban a previously kicked user in a supergroup.
864
     * The user will not return to the group automatically, but will be able to join via link, etc.
865
     * The bot must be an administrator in the group for this to work. Returns True on success.
866
     *
867
     * @param int|string $chatId Unique identifier for the target group
868
     * or username of the target supergroup (in the format @supergroupusername)
869
     * @param int $userId Unique identifier of the target user
870
     *
871
     * @return bool
872
     */
873
    public function unbanChatMember($chatId, $userId)
874
    {
875
        return $this->call('unbanChatMember', [
876
            'chat_id' => $chatId,
877
            'user_id' => $userId,
878
        ]);
879
    }
880
881
    /**
882
     * Use this method to send answers to callback queries sent from inline keyboards.
883
     * The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.
884
     *
885
     * @param $callbackQueryId
886
     * @param null $text
887
     * @param bool $showAlert
888
     *
889
     * @return bool
890
     */
891
    public function answerCallbackQuery($callbackQueryId, $text = null, $showAlert = false)
892
    {
893
        return $this->call('answerCallbackQuery', [
894
            'callback_query_id' => $callbackQueryId,
895
            'text' => $text,
896
            'show_alert' => (bool)$showAlert,
897
        ]);
898
    }
899
900
901
    /**
902
     * Use this method to edit text messages sent by the bot or via the bot
903
     *
904
     * @param int|string $chatId
905
     * @param int $messageId
906
     * @param string $text
907
     * @param string|null $parseMode
908
     * @param bool $disablePreview
909
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
910
     *
911
     * @return \TelegramBot\Api\Types\Message
912
     * @throws \TelegramBot\Api\InvalidArgumentException
913
     * @throws \TelegramBot\Api\Exception
914
     */
915 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...
916
        $chatId,
917
        $messageId,
918
        $text,
919
        $parseMode = null,
920
        $disablePreview = false,
921
        $replyMarkup = null
922
    ) {
923
        return Message::fromResponse($this->call('editMessageText', [
924
            'chat_id' => $chatId,
925
            'message_id' => $messageId,
926
            'text' => $text,
927
            'parse_mode' => $parseMode,
928
            'disable_web_page_preview' => $disablePreview,
929
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
930
        ]));
931
    }
932
933
    /**
934
     * Use this method to edit text messages sent by the bot or via the bot
935
     *
936
     * @param int|string $chatId
937
     * @param int $messageId
938
     * @param string|null $caption
939
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
940
     *
941
     * @return \TelegramBot\Api\Types\Message
942
     * @throws \TelegramBot\Api\InvalidArgumentException
943
     * @throws \TelegramBot\Api\Exception
944
     */
945 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...
946
        $chatId,
947
        $messageId,
948
        $caption = null,
949
        $replyMarkup = null
950
    ) {
951
        return Message::fromResponse($this->call('editMessageText', [
952
            'chat_id' => $chatId,
953
            'message_id' => $messageId,
954
            'caption' => $caption,
955
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
956
        ]));
957
    }
958
959
    /**
960
     * Use this method to edit only the reply markup of messages sent by the bot or via the bot
961
     *
962
     * @param int|string $chatId
963
     * @param int $messageId
964
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
965
     *
966
     * @return \TelegramBot\Api\Types\Message
967
     * @throws \TelegramBot\Api\InvalidArgumentException
968
     * @throws \TelegramBot\Api\Exception
969
     */
970 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...
971
        $chatId,
972
        $messageId,
973
        $replyMarkup = null
974
    ) {
975
        return Message::fromResponse($this->call('editMessageText', [
976
            'chat_id' => $chatId,
977
            'message_id' => $messageId,
978
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
979
        ]));
980
    }
981
982
    /**
983
     * Close curl
984
     */
985 9
    public function __destruct()
986
    {
987 9
        $this->curl && curl_close($this->curl);
988 9
    }
989
990
    /**
991
     * @return string
992
     */
993
    public function getUrl()
994
    {
995
        return self::URL_PREFIX.$this->token;
996
    }
997
998
    /**
999
     * @return string
1000
     */
1001
    public function getFileUrl()
1002
    {
1003
        return self::FILE_URL_PREFIX.$this->token;
1004
    }
1005
1006
    /**
1007
     * @param \TelegramBot\Api\Types\Update $update
1008
     * @param string $eventName
1009
     *
1010
     * @throws \TelegramBot\Api\Exception
1011
     */
1012
    public function trackUpdate(Update $update, $eventName = 'Message')
1013
    {
1014
        if (!in_array($update->getUpdateId(), $this->trackedEvents)) {
1015
            $this->trackedEvents[] = $update->getUpdateId();
1016
1017
            $this->track($update->getMessage(), $eventName);
1018
1019
            if (count($this->trackedEvents) > self::MAX_TRACKED_EVENTS) {
1020
                $this->trackedEvents = array_slice($this->trackedEvents, round(self::MAX_TRACKED_EVENTS / 4));
1021
            }
1022
        }
1023
    }
1024
1025
    /**
1026
     * Wrapper for tracker
1027
     *
1028
     * @param \TelegramBot\Api\Types\Message $message
1029
     * @param string $eventName
1030
     *
1031
     * @throws \TelegramBot\Api\Exception
1032
     */
1033
    public function track(Message $message, $eventName = 'Message')
1034
    {
1035
        if ($this->tracker instanceof Botan) {
1036
            $this->tracker->track($message, $eventName);
1037
        }
1038
    }
1039
}
1040