Completed
Push — master ( 84868c...645e8e )
by Gusev
02:51
created

BotApi::sendAudio()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 21
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 5
Bugs 2 Features 2
Metric Value
c 5
b 2
f 2
dl 0
loc 21
ccs 0
cts 0
cp 0
rs 9.3142
cc 2
eloc 18
nc 1
nop 8
crap 6

How to fix   Many Parameters   

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace TelegramBot\Api;
4
5
use TelegramBot\Api\Types\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 to send phone contacts
318
     *
319
     * @param int $chatId
320
     * @param string $phoneNumber
321
     * @param string $firstName
322
     * @param string $lastName
323
     * @param int|null $replyToMessageId
324
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
325
     * @param bool $disableNotification
326
     *
327
     * @return \TelegramBot\Api\Types\Message
328
     * @throws \TelegramBot\Api\Exception
329
     */
330
    public function sendContact(
331
        $chatId,
332
        $phoneNumber,
333
        $firstName,
334
        $lastName = null,
335
        $replyToMessageId = null,
336
        $replyMarkup = null,
337
        $disableNotification = false
338
    ) {
339
        return Message::fromResponse($this->call('sendContact', [
340
            'chat_id' => $chatId,
341
            'phone_number' => $phoneNumber,
342
            'first_name' => $firstName,
343
            'last_name' => $lastName,
344
            'reply_to_message_id' => $replyToMessageId,
345
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
346
            'disable_notification' => (bool)$disableNotification,
347
        ]));
348
    }
349
350
    /**
351
     * Use this method when you need to tell the user that something is happening on the bot's side.
352
     * The status is set for 5 seconds or less (when a message arrives from your bot,
353
     * Telegram clients clear its typing status).
354
     *
355
     * We only recommend using this method when a response from the bot will take a noticeable amount of time to arrive.
356
     *
357
     * Type of action to broadcast. Choose one, depending on what the user is about to receive:
358
     * `typing` for text messages, `upload_photo` for photos, `record_video` or `upload_video` for videos,
359
     * `record_audio` or upload_audio for audio files, `upload_document` for general files,
360
     * `find_location` for location data.
361
     *
362
     * @param int $chatId
363
     * @param string $action
364
     *
365
     * @return bool
366
     * @throws \TelegramBot\Api\Exception
367
     */
368
    public function sendChatAction($chatId, $action)
369
    {
370
        return $this->call('sendChatAction', [
371
            'chat_id' => $chatId,
372
            'action' => $action
373
        ]);
374
    }
375
376
    /**
377
     * Use this method to get a list of profile pictures for a user.
378
     *
379
     * @param int $userId
380
     * @param int $offset
381
     * @param int $limit
382
     *
383
     * @return \TelegramBot\Api\Types\UserProfilePhotos
384
     * @throws \TelegramBot\Api\Exception
385
     */
386
    public function getUserProfilePhotos($userId, $offset = 0, $limit = 100)
387
    {
388
        return UserProfilePhotos::fromResponse($this->call('getUserProfilePhotos', [
389
            'user_id' => (int) $userId,
390
            'offset' => (int) $offset,
391
            'limit' => (int) $limit,
392
        ]));
393
    }
394
395
    /**
396
     * Use this method to specify a url and receive incoming updates via an outgoing webhook.
397
     * Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url,
398
     * containing a JSON-serialized Update.
399
     * In case of an unsuccessful request, we will give up after a reasonable amount of attempts.
400
     *
401
     * @param string $url HTTPS url to send updates to. Use an empty string to remove webhook integration
402
     * @param \CURLFile|string $certificate Upload your public key certificate
403
     *                                      so that the root certificate in use can be checked
404
     *
405
     * @return string
406
     *
407
     * @throws \TelegramBot\Api\Exception
408
     */
409
    public function setWebhook($url = '', $certificate = null)
410
    {
411
        return $this->call('setWebhook', ['url' => $url, 'certificate' => $certificate]);
412
    }
413
414
    /**
415
     * A simple method for testing your bot's auth token.Requires no parameters.
416
     * Returns basic information about the bot in form of a User object.
417
     *
418
     * @return \TelegramBot\Api\Types\User
419
     * @throws \TelegramBot\Api\Exception
420
     * @throws \TelegramBot\Api\InvalidArgumentException
421
     */
422
    public function getMe()
423
    {
424
        return User::fromResponse($this->call('getMe'));
425
    }
426
427
    /**
428
     * Use this method to receive incoming updates using long polling.
429
     * An Array of Update objects is returned.
430
     *
431
     * Notes
432
     * 1. This method will not work if an outgoing webhook is set up.
433
     * 2. In order to avoid getting duplicate updates, recalculate offset after each server response.
434
     *
435
     * @param int $offset
436
     * @param int $limit
437
     * @param int $timeout
438
     *
439
     * @return Update[]
440
     * @throws \TelegramBot\Api\Exception
441
     * @throws \TelegramBot\Api\InvalidArgumentException
442
     */
443 2
    public function getUpdates($offset = 0, $limit = 100, $timeout = 0)
444
    {
445 2
        $updates = ArrayOfUpdates::fromResponse($this->call('getUpdates', [
446 2
            'offset' => $offset,
447 2
            'limit' => $limit,
448
            'timeout' => $timeout
449 2
        ]));
450
451 2
        if ($this->tracker instanceof Botan) {
452
            foreach ($updates as $update) {
453
                $this->trackUpdate($update);
454
            }
455
        }
456
457 2
        return $updates;
458
    }
459
460
    /**
461
     * Use this method to send point on the map. On success, the sent Message is returned.
462
     *
463
     * @param int $chatId
464
     * @param float $latitude
465
     * @param float $longitude
466
     * @param int|null $replyToMessageId
467
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
468
     * @param bool $disableNotification
469
     *
470
     * @return \TelegramBot\Api\Types\Message
471
     * @throws \TelegramBot\Api\Exception
472
     */
473
    public function sendLocation(
474
        $chatId,
475
        $latitude,
476
        $longitude,
477
        $replyToMessageId = null,
478
        $replyMarkup = null,
479
        $disableNotification = false
480
    ) {
481
        return Message::fromResponse($this->call('sendLocation', [
482
            'chat_id' => $chatId,
483
            'latitude' => $latitude,
484
            'longitude' => $longitude,
485
            'reply_to_message_id' => $replyToMessageId,
486
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
487
            'disable_notification' => (bool) $disableNotification
488
    }
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected '}', expecting ']'
Loading history...
489
490
    /**
491
     * Use this method to send information about a venue. On success, the sent Message is returned.
492
     *
493
     * @param int|string $chatId
494
     * @param float $latitude
495
     * @param float $longitude
496
     * @param string $title
497
     * @param string $address
498
     * @param string|null $foursquareId
499
     * @param int|null $replyToMessageId
500
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
501
     * @param bool $disableNotification
502
     *
503
     * @return \TelegramBot\Api\Types\Message
504
     * @throws \TelegramBot\Api\Exception
505
     */
506
    public function sendVenue(
507
        $chatId,
508
        $latitude,
509
        $longitude,
510
        $title,
511
        $address,
512
        $foursquareId = null,
513
        $replyToMessageId = null,
514
        $replyMarkup = null,
515
        $disableNotification = false
516
    ) {
517
        return Message::fromResponse($this->call('sendVenue', [
518
            'chat_id' => $chatId,
519
            'latitude' => $latitude,
520
            'longitude' => $longitude,
521
            'title' => $title,
522
            'address' => $address,
523
            'foursquare_id' => $foursquareId,
524
            'reply_to_message_id' => $replyToMessageId,
525
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
526
            'disable_notification' => (bool)$disableNotification,
527
        ]));
528
    }
529
530
    /**
531
     * Use this method to send .webp stickers. On success, the sent Message is returned.
532
     *
533
     * @param int $chatId
534
     * @param \CURLFile|string $sticker
535
     * @param int|null $replyToMessageId
536
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
537
     * @param bool $disableNotification
538
     *
539
     * @return \TelegramBot\Api\Types\Message
540
     * @throws \TelegramBot\Api\InvalidArgumentException
541
     * @throws \TelegramBot\Api\Exception
542
     */
543
    public function sendSticker(
544
        $chatId,
545
        $sticker,
546
        $replyToMessageId = null,
547
        $replyMarkup = null,
548
        $disableNotification = false
549
    ) {
550
        return Message::fromResponse($this->call('sendSticker', [
551
            'chat_id' => $chatId,
552
            'sticker' => $sticker,
553
            'reply_to_message_id' => $replyToMessageId,
554
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
555
            'disable_notification' => (bool) $disableNotification
556
        ]));
557
    }
558
559
    /**
560
     * Use this method to send video files,
561
     * Telegram clients support mp4 videos (other formats may be sent as Document).
562
     * On success, the sent Message is returned.
563
     *
564
     * @param int $chatId
565
     * @param \CURLFile|string $video
566
     * @param int|null $duration
567
     * @param string|null $caption
568
     * @param int|null $replyToMessageId
569
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
570
     * @param bool $disableNotification
571
     *
572
     * @return \TelegramBot\Api\Types\Message
573
     * @throws \TelegramBot\Api\InvalidArgumentException
574
     * @throws \TelegramBot\Api\Exception
575
     */
576
    public function sendVideo(
577
        $chatId,
578
        $video,
579
        $duration = null,
580
        $caption = null,
581
        $replyToMessageId = null,
582
        $replyMarkup = null,
583
        $disableNotification = false
584
    ) {
585
        return Message::fromResponse($this->call('sendVideo', [
586
            'chat_id' => $chatId,
587
            'video' => $video,
588
            'duration' => $duration,
589
            'caption' => $caption,
590
            'reply_to_message_id' => $replyToMessageId,
591
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
592
            'disable_notification' => (bool) $disableNotification
593
        ]));
594
    }
595
596
    /**
597
     * Use this method to send audio files,
598
     * if you want Telegram clients to display the file as a playable voice message.
599
     * For this to work, your audio must be in an .ogg file encoded with OPUS
600
     * (other formats may be sent as Audio or Document).
601
     * On success, the sent Message is returned.
602
     * Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future.
603
     *
604
     * @param int $chatId
605
     * @param \CURLFile|string $voice
606
     * @param int|null $duration
607
     * @param int|null $replyToMessageId
608
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
609
     * @param bool $disableNotification
610
     *
611
     * @return \TelegramBot\Api\Types\Message
612
     * @throws \TelegramBot\Api\InvalidArgumentException
613
     * @throws \TelegramBot\Api\Exception
614
     */
615
    public function sendVoice(
616
        $chatId,
617
        $voice,
618
        $duration = null,
619
        $replyToMessageId = null,
620
        $replyMarkup = null,
621
        $disableNotification = false
622
    ) {
623
        return Message::fromResponse($this->call('sendVoice', [
624
            'chat_id' => $chatId,
625
            'voice' => $voice,
626
            'duration' => $duration,
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 forward messages of any kind. On success, the sent Message is returned.
635
     *
636
     * @param int $chatId
637
     * @param int $fromChatId
638
     * @param int $messageId
639
     * @param bool $disableNotification
640
     *
641
     * @return \TelegramBot\Api\Types\Message
642
     * @throws \TelegramBot\Api\InvalidArgumentException
643
     * @throws \TelegramBot\Api\Exception
644
     */
645
    public function forwardMessage($chatId, $fromChatId, $messageId, $disableNotification = false)
646
    {
647
        return Message::fromResponse($this->call('forwardMessage', [
648
            'chat_id' => $chatId,
649
            'from_chat_id' => $fromChatId,
650
            'message_id' => (int) $messageId,
651
            'disable_notification' => (bool) $disableNotification
652
        ]));
653
    }
654
655
    /**
656
     * Use this method to send audio files,
657
     * if you want Telegram clients to display them in the music player.
658
     * Your audio must be in the .mp3 format.
659
     * On success, the sent Message is returned.
660
     * Bots can currently send audio files of up to 50 MB in size, this limit may be changed in the future.
661
     *
662
     * For backward compatibility, when the fields title and performer are both empty
663
     * and the mime-type of the file to be sent is not audio/mpeg, the file will be sent as a playable voice message.
664
     * For this to work, the audio must be in an .ogg file encoded with OPUS.
665
     * This behavior will be phased out in the future. For sending voice messages, use the sendVoice method instead.
666
     *
667
     * @deprecated since 20th February. Removed backward compatibility from the method sendAudio.
668
     * Voice messages now must be sent using the method sendVoice.
669
     * There is no more need to specify a non-empty title or performer while sending the audio by file_id.
670
     *
671
     * @param int $chatId
672
     * @param \CURLFile|string $audio
673
     * @param int|null $duration
674
     * @param string|null $performer
675
     * @param string|null $title
676
     * @param int|null $replyToMessageId
677
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
678
     * @param bool $disableNotification
679
     *
680
     * @return \TelegramBot\Api\Types\Message
681
     * @throws \TelegramBot\Api\InvalidArgumentException
682
     * @throws \TelegramBot\Api\Exception
683
     */
684
    public function sendAudio(
685
        $chatId,
686
        $audio,
687
        $duration = null,
688
        $performer = null,
689
        $title = null,
690
        $replyToMessageId = null,
691
        $replyMarkup = null,
692
        $disableNotification = false
693
    ) {
694
        return Message::fromResponse($this->call('sendAudio', [
695
            'chat_id' => $chatId,
696
            'audio' => $audio,
697
            'duration' => $duration,
698
            'performer' => $performer,
699
            'title' => $title,
700
            'reply_to_message_id' => $replyToMessageId,
701
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
702
            'disable_notification' => (bool) $disableNotification
703
        ]));
704
    }
705
706
    /**
707
     * Use this method to send photos. On success, the sent Message is returned.
708
     *
709
     * @param int $chatId
710
     * @param \CURLFile|string $photo
711
     * @param string|null $caption
712
     * @param int|null $replyToMessageId
713
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
714
     * @param bool $disableNotification
715
     *
716
     * @return \TelegramBot\Api\Types\Message
717
     * @throws \TelegramBot\Api\InvalidArgumentException
718
     * @throws \TelegramBot\Api\Exception
719
     */
720
    public function sendPhoto(
721
        $chatId,
722
        $photo,
723
        $caption = null,
724
        $replyToMessageId = null,
725
        $replyMarkup = null,
726
        $disableNotification = false
727
    ) {
728
        return Message::fromResponse($this->call('sendPhoto', [
729
            'chat_id' => $chatId,
730
            'photo' => $photo,
731
            'caption' => $caption,
732
            'reply_to_message_id' => $replyToMessageId,
733
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
734
            'disable_notification' => (bool) $disableNotification
735
        ]));
736
    }
737
738
    /**
739
     * Use this method to send general files. On success, the sent Message is returned.
740
     * Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future.
741
     *
742
     * @param int $chatId
743
     * @param \CURLFile|string $document
744
     * @param int|null $replyToMessageId
745
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
746
     * @param bool $disableNotification
747
     *
748
     * @return \TelegramBot\Api\Types\Message
749
     * @throws \TelegramBot\Api\InvalidArgumentException
750
     * @throws \TelegramBot\Api\Exception
751
     */
752
    public function sendDocument(
753
        $chatId,
754
        $document,
755
        $replyToMessageId = null,
756
        $replyMarkup = null,
757
        $disableNotification = false
758
    ) {
759
        return Message::fromResponse($this->call('sendDocument', [
760
            'chat_id' => $chatId,
761
            'document' => $document,
762
            'reply_to_message_id' => $replyToMessageId,
763
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
764
            'disable_notification' => (bool) $disableNotification
765
        ]));
766
    }
767
768
    /**
769
     * Use this method to get basic info about a file and prepare it for downloading.
770
     * For the moment, bots can download files of up to 20MB in size.
771
     * On success, a File object is returned.
772
     * The file can then be downloaded via the link https://api.telegram.org/file/bot<token>/<file_path>,
773
     * where <file_path> is taken from the response.
774
     * It is guaranteed that the link will be valid for at least 1 hour.
775
     * When the link expires, a new one can be requested by calling getFile again.
776
     *
777
     * @param $fileId
778
     *
779
     * @return \TelegramBot\Api\Types\File
780
     * @throws \TelegramBot\Api\InvalidArgumentException
781
     * @throws \TelegramBot\Api\Exception
782
     */
783
    public function getFile($fileId)
784
    {
785
        return File::fromResponse($this->call('getFile', ['file_id' => $fileId]));
786
    }
787
788
    /**
789
     * Get file contents via cURL
790
     *
791
     * @param $fileId
792
     *
793
     * @return string
794
     *
795
     * @throws \TelegramBot\Api\HttpException
796
     */
797
    public function downloadFile($fileId)
798
    {
799
        $file = $this->getFile($fileId);
800
        $options = [
801
            CURLOPT_HEADER => 0,
802
            CURLOPT_HTTPGET => 1,
803
            CURLOPT_RETURNTRANSFER => 1,
804
            CURLOPT_URL => $this->getFileUrl() . '/' . $file->getFilePath()
805
        ];
806
807
        return $this->executeCurl($options);
808
    }
809
810
    /**
811
     * Use this method to send answers to an inline query. On success, True is returned.
812
     * No more than 50 results per query are allowed.
813
     *
814
     * @param string $inlineQueryId
815
     * @param \TelegramBot\Api\Types\Inline\AbstractInlineQueryResult[] $results
816
     * @param int $cacheTime
817
     * @param bool $isPersonal
818
     * @param string $nextOffset
819
     *
820
     * @return mixed
821
     * @throws Exception
822
     */
823
    public function answerInlineQuery($inlineQueryId, $results, $cacheTime = 300, $isPersonal = false, $nextOffset = '')
824
    {
825
        $results = array_map(function ($item) {
826
            /* @var \TelegramBot\Api\Types\Inline\AbstractInlineQueryResult $item */
827
828
            return json_decode($item->toJson(), true);
829
        }, $results);
830
831
        return $this->call('answerInlineQuery', [
832
            'inline_query_id' => $inlineQueryId,
833
            'results' => json_encode($results),
834
            'cache_time' => $cacheTime,
835
            'is_personal' => $isPersonal,
836
            'next_offset' => $nextOffset,
837
        ]);
838
    }
839
840
    /**
841
     * Use this method to kick a user from a group or a supergroup.
842
     * In the case of supergroups, the user will not be able to return to the group
843
     * on their own using invite links, etc., unless unbanned first.
844
     * The bot must be an administrator in the group for this to work. Returns True on success.
845
     *
846
     * @param int|string $chatId Unique identifier for the target group
847
     * or username of the target supergroup (in the format @supergroupusername)
848
     * @param int $userId Unique identifier of the target user
849
     *
850
     * @return bool
851
     */
852
    public function kickChatMember($chatId, $userId)
853
    {
854
        return $this->call('kickChatMember', [
855
            'chat_id' => $chatId,
856
            'user_id' => $userId,
857
        ]);
858
    }
859
860
    /**
861
     * Use this method to unban a previously kicked user in a supergroup.
862
     * The user will not return to the group automatically, but will be able to join via link, etc.
863
     * The bot must be an administrator in the group for this to work. Returns True on success.
864
     *
865
     * @param int|string $chatId Unique identifier for the target group
866
     * or username of the target supergroup (in the format @supergroupusername)
867
     * @param int $userId Unique identifier of the target user
868
     *
869
     * @return bool
870
     */
871
    public function unbanChatMember($chatId, $userId)
872
    {
873
        return $this->call('unbanChatMember', [
874
            'chat_id' => $chatId,
875
            'user_id' => $userId,
876
        ]);
877
    }
878
879
    /**
880
     * Use this method to send answers to callback queries sent from inline keyboards.
881
     * The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.
882
     *
883
     * @param $callbackQueryId
884
     * @param null $text
885
     * @param bool $showAlert
886
     *
887
     * @return bool
888
     */
889
    public function answerCallbackQuery($callbackQueryId, $text = null, $showAlert = false)
890
    {
891
        return $this->call('answerCallbackQuery', [
892
            'callback_query_id' => $callbackQueryId,
893
            'text' => $text,
894
            'show_alert' => (bool)$showAlert,
895
        ]);
896
    }
897
898
899
    /**
900
     * Use this method to edit text messages sent by the bot or via the bot
901
     *
902
     * @param int|string $chatId
903
     * @param int $messageId
904
     * @param string $text
905
     * @param string|null $parseMode
906
     * @param bool $disablePreview
907
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
908
     *
909
     * @return \TelegramBot\Api\Types\Message
910
     * @throws \TelegramBot\Api\InvalidArgumentException
911
     * @throws \TelegramBot\Api\Exception
912
     */
913
    public function editMessageText(
914
        $chatId,
915
        $messageId,
916
        $text,
917
        $parseMode = null,
918
        $disablePreview = false,
919
        $replyMarkup = null
920
    ) {
921
        return Message::fromResponse($this->call('editMessageText', [
922
            'chat_id' => $chatId,
923
            'message_id' => $messageId,
924
            'text' => $text,
925
            'parse_mode' => $parseMode,
926
            'disable_web_page_preview' => $disablePreview,
927
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
928
        ]));
929
    }
930
931
    /**
932
     * Use this method to edit text messages sent by the bot or via the bot
933
     *
934
     * @param int|string $chatId
935
     * @param int $messageId
936
     * @param string|null $caption
937
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
938
     *
939
     * @return \TelegramBot\Api\Types\Message
940
     * @throws \TelegramBot\Api\InvalidArgumentException
941
     * @throws \TelegramBot\Api\Exception
942
     */
943
    public function editMessageCaption(
944 9
        $chatId,
945
        $messageId,
946 9
        $caption = null,
947 9
        $replyMarkup = null
948
    ) {
949
        return Message::fromResponse($this->call('editMessageText', [
950
            'chat_id' => $chatId,
951
            'message_id' => $messageId,
952
            'caption' => $caption,
953
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
954
        ]));
955
    }
956
957
    /**
958
     * Use this method to edit only the reply markup of messages sent by the bot or via the bot
959
     *
960
     * @param int|string $chatId
961
     * @param int $messageId
962
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
963
     *
964
     * @return \TelegramBot\Api\Types\Message
965
     * @throws \TelegramBot\Api\InvalidArgumentException
966
     * @throws \TelegramBot\Api\Exception
967
     */
968
    public function editMessageReplyMarkup(
969
        $chatId,
970
        $messageId,
971
        $replyMarkup = null
972
    ) {
973
        return Message::fromResponse($this->call('editMessageText', [
974
            'chat_id' => $chatId,
975
            'message_id' => $messageId,
976
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
977
        ]));
978
    }
979
980
    /**
981
     * Close curl
982
     */
983
    public function __destruct()
984
    {
985
        $this->curl && curl_close($this->curl);
986
    }
987
988
    /**
989
     * @return string
990
     */
991
    public function getUrl()
992
    {
993
        return self::URL_PREFIX . $this->token;
994
    }
995
996
    /**
997
     * @return string
998
     */
999
    public function getFileUrl()
1000
    {
1001
        return self::FILE_URL_PREFIX . $this->token;
1002
    }
1003
1004
    /**
1005
     * @param \TelegramBot\Api\Types\Update $update
1006
     * @param string $eventName
1007
     *
1008
     * @throws \TelegramBot\Api\Exception
1009
     */
1010
    public function trackUpdate(Update $update, $eventName = 'Message')
1011
    {
1012
        if (!in_array($update->getUpdateId(), $this->trackedEvents)) {
1013
            $this->trackedEvents[] = $update->getUpdateId();
1014
1015
            $this->track($update->getMessage(), $eventName);
1016
1017
            if (count($this->trackedEvents) > self::MAX_TRACKED_EVENTS) {
1018
                $this->trackedEvents = array_slice($this->trackedEvents, round(self::MAX_TRACKED_EVENTS / 4));
1019
            }
1020
        }
1021
    }
1022
1023
    /**
1024
     * Wrapper for tracker
1025
     *
1026
     * @param \TelegramBot\Api\Types\Message $message
1027
     * @param string $eventName
1028
     *
1029
     * @throws \TelegramBot\Api\Exception
1030
     */
1031
    public function track(Message $message, $eventName = 'Message')
1032
    {
1033
        if ($this->tracker instanceof Botan) {
1034
            $this->tracker->track($message, $eventName);
1035
        }
1036
    }
1037
}
1038