Passed
Push — master ( af3a0b...87be02 )
by
unknown
03:36
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 0
Metric Value
dl 0
loc 21
ccs 0
cts 0
cp 0
rs 9.3142
c 0
b 0
f 0
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\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
        if ($result === false) {
243
            throw new HttpException(curl_error($this->curl), curl_errno($this->curl));
244
        }
245
246
        return $result;
247
    }
248
249
    /**
250
     * Response validation
251
     *
252
     * @param resource $curl
253
     *
254
     * @throws \TelegramBot\Api\HttpException
255
     */
256
    public static function curlValidate($curl)
257
    {
258
        if (($httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE))
259
            && !in_array($httpCode, [self::DEFAULT_STATUS_CODE, self::NOT_MODIFIED_STATUS_CODE])
260
        ) {
261
            throw new HttpException(self::$codes[$httpCode], $httpCode);
262
        }
263
    }
264
265
    /**
266
     * JSON validation
267
     *
268
     * @param string $jsonString
269
     * @param boolean $asArray
270
     *
271
     * @return object|array
272
     * @throws \TelegramBot\Api\InvalidJsonException
273
     */
274
    public static function jsonValidate($jsonString, $asArray)
275
    {
276
        $json = json_decode($jsonString, $asArray);
277
278
        if (json_last_error() != JSON_ERROR_NONE) {
279
            throw new InvalidJsonException(json_last_error_msg(), json_last_error());
280
        }
281
282
        return $json;
283
    }
284
285
    /**
286
     * Use this method to send text messages. On success, the sent \TelegramBot\Api\Types\Message is returned.
287
     *
288
     * @param int|string $chatId
289
     * @param string $text
290
     * @param string|null $parseMode
291
     * @param bool $disablePreview
292
     * @param int|null $replyToMessageId
293
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
294
     * @param bool $disableNotification
295
     *
296
     * @return \TelegramBot\Api\Types\Message
297
     * @throws \TelegramBot\Api\InvalidArgumentException
298
     * @throws \TelegramBot\Api\Exception
299
     */
300
    public function sendMessage(
301
        $chatId,
302
        $text,
303
        $parseMode = null,
304
        $disablePreview = false,
305
        $replyToMessageId = null,
306
        $replyMarkup = null,
307
        $disableNotification = false
308
    ) {
309
        return Message::fromResponse($this->call('sendMessage', [
310
            'chat_id' => $chatId,
311
            'text' => $text,
312
            'parse_mode' => $parseMode,
313
            'disable_web_page_preview' => $disablePreview,
314
            'reply_to_message_id' => (int)$replyToMessageId,
315
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
316
            'disable_notification' => (bool)$disableNotification,
317
        ]));
318
    }
319
320
    /**
321
     * Use this method to send phone contacts
322
     *
323
     * @param int|string $chatId chat_id or @channel_name
324
     * @param string $phoneNumber
325
     * @param string $firstName
326
     * @param string $lastName
327
     * @param int|null $replyToMessageId
328
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
329
     * @param bool $disableNotification
330
     *
331
     * @return \TelegramBot\Api\Types\Message
332
     * @throws \TelegramBot\Api\Exception
333
     */
334 View Code Duplication
    public function sendContact(
335
        $chatId,
336
        $phoneNumber,
337
        $firstName,
338
        $lastName = null,
339
        $replyToMessageId = null,
340
        $replyMarkup = null,
341
        $disableNotification = false
342
    ) {
343
        return Message::fromResponse($this->call('sendContact', [
344
            'chat_id' => $chatId,
345
            'phone_number' => $phoneNumber,
346
            'first_name' => $firstName,
347
            'last_name' => $lastName,
348
            'reply_to_message_id' => $replyToMessageId,
349
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
350
            'disable_notification' => (bool)$disableNotification,
351
        ]));
352
    }
353
354
    /**
355
     * Use this method when you need to tell the user that something is happening on the bot's side.
356
     * The status is set for 5 seconds or less (when a message arrives from your bot,
357
     * Telegram clients clear its typing status).
358
     *
359
     * We only recommend using this method when a response from the bot will take a noticeable amount of time to arrive.
360
     *
361
     * Type of action to broadcast. Choose one, depending on what the user is about to receive:
362
     * `typing` for text messages, `upload_photo` for photos, `record_video` or `upload_video` for videos,
363
     * `record_audio` or upload_audio for audio files, `upload_document` for general files,
364
     * `find_location` for location data.
365
     *
366
     * @param int $chatId
367
     * @param string $action
368
     *
369
     * @return bool
370
     * @throws \TelegramBot\Api\Exception
371
     */
372
    public function sendChatAction($chatId, $action)
373
    {
374
        return $this->call('sendChatAction', [
375
            'chat_id' => $chatId,
376
            'action' => $action,
377
        ]);
378
    }
379
380
    /**
381
     * Use this method to get a list of profile pictures for a user.
382
     *
383
     * @param int $userId
384
     * @param int $offset
385
     * @param int $limit
386
     *
387
     * @return \TelegramBot\Api\Types\UserProfilePhotos
388
     * @throws \TelegramBot\Api\Exception
389
     */
390
    public function getUserProfilePhotos($userId, $offset = 0, $limit = 100)
391
    {
392
        return UserProfilePhotos::fromResponse($this->call('getUserProfilePhotos', [
393
            'user_id' => (int)$userId,
394
            'offset' => (int)$offset,
395
            'limit' => (int)$limit,
396
        ]));
397
    }
398
399
    /**
400
     * Use this method to specify a url and receive incoming updates via an outgoing webhook.
401
     * Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url,
402
     * containing a JSON-serialized Update.
403
     * In case of an unsuccessful request, we will give up after a reasonable amount of attempts.
404
     *
405
     * @param string $url HTTPS url to send updates to. Use an empty string to remove webhook integration
406
     * @param \CURLFile|string $certificate Upload your public key certificate
407
     *                                      so that the root certificate in use can be checked
408
     *
409
     * @return string
410
     *
411
     * @throws \TelegramBot\Api\Exception
412
     */
413
    public function setWebhook($url = '', $certificate = null)
414
    {
415
        return $this->call('setWebhook', ['url' => $url, 'certificate' => $certificate]);
416
    }
417
418
    /**
419
     * A simple method for testing your bot's auth token.Requires no parameters.
420
     * Returns basic information about the bot in form of a User object.
421
     *
422
     * @return \TelegramBot\Api\Types\User
423
     * @throws \TelegramBot\Api\Exception
424
     * @throws \TelegramBot\Api\InvalidArgumentException
425
     */
426
    public function getMe()
427
    {
428
        return User::fromResponse($this->call('getMe'));
429
    }
430
431
    /**
432
     * Use this method to receive incoming updates using long polling.
433
     * An Array of Update objects is returned.
434
     *
435
     * Notes
436
     * 1. This method will not work if an outgoing webhook is set up.
437
     * 2. In order to avoid getting duplicate updates, recalculate offset after each server response.
438
     *
439
     * @param int $offset
440
     * @param int $limit
441
     * @param int $timeout
442
     *
443
     * @return Update[]
444
     * @throws \TelegramBot\Api\Exception
445
     * @throws \TelegramBot\Api\InvalidArgumentException
446
     */
447 2
    public function getUpdates($offset = 0, $limit = 100, $timeout = 0)
448
    {
449 2
        $updates = ArrayOfUpdates::fromResponse($this->call('getUpdates', [
450 2
            'offset' => $offset,
451 2
            'limit' => $limit,
452 2
            'timeout' => $timeout,
453 2
        ]));
454
455 2
        if ($this->tracker instanceof Botan) {
456
            foreach ($updates as $update) {
457
                $this->trackUpdate($update);
458
            }
459
        }
460
461 2
        return $updates;
462
    }
463
464
    /**
465
     * Use this method to send point on the map. On success, the sent Message is returned.
466
     *
467
     * @param int $chatId
468
     * @param float $latitude
469
     * @param float $longitude
470
     * @param int|null $replyToMessageId
471
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
472
     * @param bool $disableNotification
473
     *
474
     * @return \TelegramBot\Api\Types\Message
475
     * @throws \TelegramBot\Api\Exception
476
     */
477 View Code Duplication
    public function sendLocation(
478
        $chatId,
479
        $latitude,
480
        $longitude,
481
        $replyToMessageId = null,
482
        $replyMarkup = null,
483
        $disableNotification = false
484
    ) {
485
        return Message::fromResponse($this->call('sendLocation', [
486
            'chat_id' => $chatId,
487
            'latitude' => $latitude,
488
            'longitude' => $longitude,
489
            'reply_to_message_id' => $replyToMessageId,
490
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
491
            'disable_notification' => (bool)$disableNotification,
492
        ]));
493
    }
494
495
    /**
496
     * Use this method to send information about a venue. On success, the sent Message is returned.
497
     *
498
     * @param int|string $chatId chat_id or @channel_name
499
     * @param float $latitude
500
     * @param float $longitude
501
     * @param string $title
502
     * @param string $address
503
     * @param string|null $foursquareId
504
     * @param int|null $replyToMessageId
505
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
506
     * @param bool $disableNotification
507
     *
508
     * @return \TelegramBot\Api\Types\Message
509
     * @throws \TelegramBot\Api\Exception
510
     */
511
    public function sendVenue(
512
        $chatId,
513
        $latitude,
514
        $longitude,
515
        $title,
516
        $address,
517
        $foursquareId = null,
518
        $replyToMessageId = null,
519
        $replyMarkup = null,
520
        $disableNotification = false
521
    ) {
522
        return Message::fromResponse($this->call('sendVenue', [
523
            'chat_id' => $chatId,
524
            'latitude' => $latitude,
525
            'longitude' => $longitude,
526
            'title' => $title,
527
            'address' => $address,
528
            'foursquare_id' => $foursquareId,
529
            'reply_to_message_id' => $replyToMessageId,
530
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
531
            'disable_notification' => (bool)$disableNotification,
532
        ]));
533
    }
534
535
    /**
536
     * Use this method to send .webp stickers. On success, the sent Message is returned.
537
     *
538
     * @param int|string $chatId chat_id or @channel_name
539
     * @param \CURLFile|string $sticker
540
     * @param int|null $replyToMessageId
541
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
542
     * @param bool $disableNotification
543
     *
544
     * @return \TelegramBot\Api\Types\Message
545
     * @throws \TelegramBot\Api\InvalidArgumentException
546
     * @throws \TelegramBot\Api\Exception
547
     */
548 View Code Duplication
    public function sendSticker(
549
        $chatId,
550
        $sticker,
551
        $replyToMessageId = null,
552
        $replyMarkup = null,
553
        $disableNotification = false
554
    ) {
555
        return Message::fromResponse($this->call('sendSticker', [
556
            'chat_id' => $chatId,
557
            'sticker' => $sticker,
558
            'reply_to_message_id' => $replyToMessageId,
559
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
560
            'disable_notification' => (bool)$disableNotification,
561
        ]));
562
    }
563
564
    /**
565
     * Use this method to send video files,
566
     * Telegram clients support mp4 videos (other formats may be sent as Document).
567
     * On success, the sent Message is returned.
568
     *
569
     * @param int|string $chatId chat_id or @channel_name
570
     * @param \CURLFile|string $video
571
     * @param int|null $duration
572
     * @param string|null $caption
573
     * @param int|null $replyToMessageId
574
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
575
     * @param bool $disableNotification
576
     *
577
     * @return \TelegramBot\Api\Types\Message
578
     * @throws \TelegramBot\Api\InvalidArgumentException
579
     * @throws \TelegramBot\Api\Exception
580
     */
581
    public function sendVideo(
582
        $chatId,
583
        $video,
584
        $duration = null,
585
        $caption = null,
586
        $replyToMessageId = null,
587
        $replyMarkup = null,
588
        $disableNotification = false
589
    ) {
590
        return Message::fromResponse($this->call('sendVideo', [
591
            'chat_id' => $chatId,
592
            'video' => $video,
593
            'duration' => $duration,
594
            'caption' => $caption,
595
            'reply_to_message_id' => $replyToMessageId,
596
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
597
            'disable_notification' => (bool)$disableNotification,
598
        ]));
599
    }
600
601
    /**
602
     * Use this method to send audio files,
603
     * if you want Telegram clients to display the file as a playable voice message.
604
     * For this to work, your audio must be in an .ogg file encoded with OPUS
605
     * (other formats may be sent as Audio or Document).
606
     * On success, the sent Message is returned.
607
     * Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future.
608
     *
609
     * @param int|string $chatId chat_id or @channel_name
610
     * @param \CURLFile|string $voice
611
     * @param int|null $duration
612
     * @param int|null $replyToMessageId
613
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
614
     * @param bool $disableNotification
615
     *
616
     * @return \TelegramBot\Api\Types\Message
617
     * @throws \TelegramBot\Api\InvalidArgumentException
618
     * @throws \TelegramBot\Api\Exception
619
     */
620 View Code Duplication
    public function sendVoice(
621
        $chatId,
622
        $voice,
623
        $duration = null,
624
        $replyToMessageId = null,
625
        $replyMarkup = null,
626
        $disableNotification = false
627
    ) {
628
        return Message::fromResponse($this->call('sendVoice', [
629
            'chat_id' => $chatId,
630
            'voice' => $voice,
631
            'duration' => $duration,
632
            'reply_to_message_id' => $replyToMessageId,
633
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
634
            'disable_notification' => (bool)$disableNotification,
635
        ]));
636
    }
637
638
    /**
639
     * Use this method to forward messages of any kind. On success, the sent Message is returned.
640
     *
641
     * @param int|string $chatId chat_id or @channel_name
642
     * @param int $fromChatId
643
     * @param int $messageId
644
     * @param bool $disableNotification
645
     *
646
     * @return \TelegramBot\Api\Types\Message
647
     * @throws \TelegramBot\Api\InvalidArgumentException
648
     * @throws \TelegramBot\Api\Exception
649
     */
650
    public function forwardMessage($chatId, $fromChatId, $messageId, $disableNotification = false)
651
    {
652
        return Message::fromResponse($this->call('forwardMessage', [
653
            'chat_id' => $chatId,
654
            'from_chat_id' => $fromChatId,
655
            'message_id' => (int)$messageId,
656
            'disable_notification' => (bool)$disableNotification,
657
        ]));
658
    }
659
660
    /**
661
     * Use this method to send audio files,
662
     * if you want Telegram clients to display them in the music player.
663
     * Your audio must be in the .mp3 format.
664
     * On success, the sent Message is returned.
665
     * Bots can currently send audio files of up to 50 MB in size, this limit may be changed in the future.
666
     *
667
     * For backward compatibility, when the fields title and performer are both empty
668
     * and the mime-type of the file to be sent is not audio/mpeg, the file will be sent as a playable voice message.
669
     * For this to work, the audio must be in an .ogg file encoded with OPUS.
670
     * This behavior will be phased out in the future. For sending voice messages, use the sendVoice method instead.
671
     *
672
     * @deprecated since 20th February. Removed backward compatibility from the method sendAudio.
673
     * Voice messages now must be sent using the method sendVoice.
674
     * There is no more need to specify a non-empty title or performer while sending the audio by file_id.
675
     *
676
     * @param int|string $chatId chat_id or @channel_name
677
     * @param \CURLFile|string $audio
678
     * @param int|null $duration
679
     * @param string|null $performer
680
     * @param string|null $title
681
     * @param int|null $replyToMessageId
682
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
683
     * @param bool $disableNotification
684
     *
685
     * @return \TelegramBot\Api\Types\Message
686
     * @throws \TelegramBot\Api\InvalidArgumentException
687
     * @throws \TelegramBot\Api\Exception
688
     */
689
    public function sendAudio(
690
        $chatId,
691
        $audio,
692
        $duration = null,
693
        $performer = null,
694
        $title = null,
695
        $replyToMessageId = null,
696
        $replyMarkup = null,
697
        $disableNotification = false
698
    ) {
699
        return Message::fromResponse($this->call('sendAudio', [
700
            'chat_id' => $chatId,
701
            'audio' => $audio,
702
            'duration' => $duration,
703
            'performer' => $performer,
704
            'title' => $title,
705
            'reply_to_message_id' => $replyToMessageId,
706
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
707
            'disable_notification' => (bool)$disableNotification,
708
        ]));
709
    }
710
711
    /**
712
     * Use this method to send photos. On success, the sent Message is returned.
713
     *
714
     * @param int|string $chatId chat_id or @channel_name
715
     * @param \CURLFile|string $photo
716
     * @param string|null $caption
717
     * @param int|null $replyToMessageId
718
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
719
     * @param bool $disableNotification
720
     *
721
     * @return \TelegramBot\Api\Types\Message
722
     * @throws \TelegramBot\Api\InvalidArgumentException
723
     * @throws \TelegramBot\Api\Exception
724
     */
725 View Code Duplication
    public function sendPhoto(
726
        $chatId,
727
        $photo,
728
        $caption = null,
729
        $replyToMessageId = null,
730
        $replyMarkup = null,
731
        $disableNotification = false
732
    ) {
733
        return Message::fromResponse($this->call('sendPhoto', [
734
            'chat_id' => $chatId,
735
            'photo' => $photo,
736
            'caption' => $caption,
737
            'reply_to_message_id' => $replyToMessageId,
738
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
739
            'disable_notification' => (bool)$disableNotification,
740
        ]));
741
    }
742
743
    /**
744
     * Use this method to send general files. On success, the sent Message is returned.
745
     * Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future.
746
     *
747
     * @param int|string $chatId chat_id or @channel_name
748
     * @param \CURLFile|string $document
749
     * @param string|null $caption
750
     * @param int|null $replyToMessageId
751
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
752
     * @param bool $disableNotification
753
     *
754
     * @return \TelegramBot\Api\Types\Message
755
     * @throws \TelegramBot\Api\InvalidArgumentException
756
     * @throws \TelegramBot\Api\Exception
757
     */
758 View Code Duplication
    public function sendDocument(
759
        $chatId,
760
        $document,
761
        $caption = null,
762
        $replyToMessageId = null,
763
        $replyMarkup = null,
764
        $disableNotification = false
765
    ) {
766
        return Message::fromResponse($this->call('sendDocument', [
767
            'chat_id' => $chatId,
768
            'document' => $document,
769
            'caption' => $caption,
770
            'reply_to_message_id' => $replyToMessageId,
771
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
772
            'disable_notification' => (bool)$disableNotification,
773
        ]));
774
    }
775
776
    /**
777
     * Use this method to get basic info about a file and prepare it for downloading.
778
     * For the moment, bots can download files of up to 20MB in size.
779
     * On success, a File object is returned.
780
     * The file can then be downloaded via the link https://api.telegram.org/file/bot<token>/<file_path>,
781
     * where <file_path> is taken from the response.
782
     * It is guaranteed that the link will be valid for at least 1 hour.
783
     * When the link expires, a new one can be requested by calling getFile again.
784
     *
785
     * @param $fileId
786
     *
787
     * @return \TelegramBot\Api\Types\File
788
     * @throws \TelegramBot\Api\InvalidArgumentException
789
     * @throws \TelegramBot\Api\Exception
790
     */
791
    public function getFile($fileId)
792
    {
793
        return File::fromResponse($this->call('getFile', ['file_id' => $fileId]));
794
    }
795
796
    /**
797
     * Get file contents via cURL
798
     *
799
     * @param $fileId
800
     *
801
     * @return string
802
     *
803
     * @throws \TelegramBot\Api\HttpException
804
     */
805
    public function downloadFile($fileId)
806
    {
807
        $file = $this->getFile($fileId);
808
        $options = [
809
            CURLOPT_HEADER => 0,
810
            CURLOPT_HTTPGET => 1,
811
            CURLOPT_RETURNTRANSFER => 1,
812
            CURLOPT_URL => $this->getFileUrl().'/'.$file->getFilePath(),
813
        ];
814
815
        return $this->executeCurl($options);
816
    }
817
818
    /**
819
     * Use this method to send answers to an inline query. On success, True is returned.
820
     * No more than 50 results per query are allowed.
821
     *
822
     * @param string $inlineQueryId
823
     * @param AbstractInlineQueryResult[] $results
824
     * @param int $cacheTime
825
     * @param bool $isPersonal
826
     * @param string $nextOffset
827
     *
828
     * @return mixed
829
     * @throws Exception
830
     */
831
    public function answerInlineQuery($inlineQueryId, $results, $cacheTime = 300, $isPersonal = false, $nextOffset = '')
832
    {
833
        $results = array_map(function ($item) {
834
            /* @var AbstractInlineQueryResult $item */
835
836
            return json_decode($item->toJson(), true);
837
        }, $results);
838
839
        return $this->call('answerInlineQuery', [
840
            'inline_query_id' => $inlineQueryId,
841
            'results' => json_encode($results),
842
            'cache_time' => $cacheTime,
843
            'is_personal' => $isPersonal,
844
            'next_offset' => $nextOffset,
845
        ]);
846
    }
847
848
    /**
849
     * Use this method to kick a user from a group or a supergroup.
850
     * In the case of supergroups, the user will not be able to return to the group
851
     * on their own using invite links, etc., unless unbanned first.
852
     * The bot must be an administrator in the group for this to work. Returns True on success.
853
     *
854
     * @param int|string $chatId Unique identifier for the target group
855
     * or username of the target supergroup (in the format @supergroupusername)
856
     * @param int $userId Unique identifier of the target user
857
     *
858
     * @return bool
859
     */
860
    public function kickChatMember($chatId, $userId)
861
    {
862
        return $this->call('kickChatMember', [
863
            'chat_id' => $chatId,
864
            'user_id' => $userId,
865
        ]);
866
    }
867
868
    /**
869
     * Use this method to unban a previously kicked user in a supergroup.
870
     * The user will not return to the group automatically, but will be able to join via link, etc.
871
     * The bot must be an administrator in the group for this to work. Returns True on success.
872
     *
873
     * @param int|string $chatId Unique identifier for the target group
874
     * or username of the target supergroup (in the format @supergroupusername)
875
     * @param int $userId Unique identifier of the target user
876
     *
877
     * @return bool
878
     */
879
    public function unbanChatMember($chatId, $userId)
880
    {
881
        return $this->call('unbanChatMember', [
882
            'chat_id' => $chatId,
883
            'user_id' => $userId,
884
        ]);
885
    }
886
887
    /**
888
     * Use this method to send answers to callback queries sent from inline keyboards.
889
     * The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.
890
     *
891
     * @param $callbackQueryId
892
     * @param null $text
893
     * @param bool $showAlert
894
     *
895
     * @return bool
896
     */
897
    public function answerCallbackQuery($callbackQueryId, $text = null, $showAlert = false)
898
    {
899
        return $this->call('answerCallbackQuery', [
900
            'callback_query_id' => $callbackQueryId,
901
            'text' => $text,
902
            'show_alert' => (bool)$showAlert,
903
        ]);
904
    }
905
906
907
    /**
908
     * Use this method to edit text messages sent by the bot or via the bot
909
     *
910
     * @param int|string $chatId
911
     * @param int $messageId
912
     * @param string $text
913
     * @param string|null $parseMode
914
     * @param bool $disablePreview
915
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
916
     *
917
     * @return \TelegramBot\Api\Types\Message
918
     * @throws \TelegramBot\Api\InvalidArgumentException
919
     * @throws \TelegramBot\Api\Exception
920
     */
921 View Code Duplication
    public function editMessageText(
922
        $chatId,
923
        $messageId,
924
        $text,
925
        $parseMode = null,
926
        $disablePreview = false,
927
        $replyMarkup = null
928
    ) {
929
        return Message::fromResponse($this->call('editMessageText', [
930
            'chat_id' => $chatId,
931
            'message_id' => $messageId,
932
            'text' => $text,
933
            'parse_mode' => $parseMode,
934
            'disable_web_page_preview' => $disablePreview,
935
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
936
        ]));
937
    }
938
939
    /**
940
     * Use this method to edit text messages sent by the bot or via the bot
941
     *
942
     * @param int|string $chatId
943
     * @param int $messageId
944
     * @param string|null $caption
945
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
946
     *
947
     * @return \TelegramBot\Api\Types\Message
948
     * @throws \TelegramBot\Api\InvalidArgumentException
949
     * @throws \TelegramBot\Api\Exception
950
     */
951 View Code Duplication
    public function editMessageCaption(
952
        $chatId,
953
        $messageId,
954
        $caption = null,
955
        $replyMarkup = null
956
    ) {
957
        return Message::fromResponse($this->call('editMessageText', [
958
            'chat_id' => $chatId,
959
            'message_id' => $messageId,
960
            'caption' => $caption,
961
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
962
        ]));
963
    }
964
965
    /**
966
     * Use this method to edit only the reply markup of messages sent by the bot or via the bot
967
     *
968
     * @param int|string $chatId
969
     * @param int $messageId
970
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
971
     *
972
     * @return \TelegramBot\Api\Types\Message
973
     * @throws \TelegramBot\Api\InvalidArgumentException
974
     * @throws \TelegramBot\Api\Exception
975
     */
976 View Code Duplication
    public function editMessageReplyMarkup(
977
        $chatId,
978
        $messageId,
979
        $replyMarkup = null
980
    ) {
981
        return Message::fromResponse($this->call('editMessageText', [
982
            'chat_id' => $chatId,
983
            'message_id' => $messageId,
984
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
985
        ]));
986
    }
987
988
    /**
989
     * Close curl
990
     */
991 9
    public function __destruct()
992
    {
993 9
        $this->curl && curl_close($this->curl);
994 9
    }
995
996
    /**
997
     * @return string
998
     */
999
    public function getUrl()
1000
    {
1001
        return self::URL_PREFIX.$this->token;
1002
    }
1003
1004
    /**
1005
     * @return string
1006
     */
1007
    public function getFileUrl()
1008
    {
1009
        return self::FILE_URL_PREFIX.$this->token;
1010
    }
1011
1012
    /**
1013
     * @param \TelegramBot\Api\Types\Update $update
1014
     * @param string $eventName
1015
     *
1016
     * @throws \TelegramBot\Api\Exception
1017
     */
1018
    public function trackUpdate(Update $update, $eventName = 'Message')
1019
    {
1020
        if (!in_array($update->getUpdateId(), $this->trackedEvents)) {
1021
            $this->trackedEvents[] = $update->getUpdateId();
1022
1023
            $this->track($update->getMessage(), $eventName);
1024
1025
            if (count($this->trackedEvents) > self::MAX_TRACKED_EVENTS) {
1026
                $this->trackedEvents = array_slice($this->trackedEvents, round(self::MAX_TRACKED_EVENTS / 4));
1027
            }
1028
        }
1029
    }
1030
1031
    /**
1032
     * Wrapper for tracker
1033
     *
1034
     * @param \TelegramBot\Api\Types\Message $message
1035
     * @param string $eventName
1036
     *
1037
     * @throws \TelegramBot\Api\Exception
1038
     */
1039
    public function track(Message $message, $eventName = 'Message')
1040
    {
1041
        if ($this->tracker instanceof Botan) {
1042
            $this->tracker->track($message, $eventName);
1043
        }
1044
    }
1045
1046
    /**
1047
     * Use this method to send invoices. On success, the sent Message is returned.
1048
     *
1049
     * @param int|string $chatId
1050
     * @param string $title
1051
     * @param string $description
1052
     * @param string $payload
1053
     * @param string $providerToken
1054
     * @param string $startParameter
1055
     * @param string $currency
1056
     * @param array $prices
1057
     * @param string|null $photoUrl
1058
     * @param int|null $photoSize
1059
     * @param int|null $photoWidth
1060
     * @param int|null $photoHeight
1061
     * @param bool $needName
1062
     * @param bool $needPhoneNumber
1063
     * @param bool $needEmail
1064
     * @param bool $needShippingAddress
1065
     * @param bool $isFlexible
1066
     * @param int|null $replyToMessageId
1067
     * @param Types\ReplyKeyboardMarkup|Types\ReplyKeyboardHide|Types\ForceReply|null $replyMarkup
1068
     * @param bool $disableNotification
1069
     *
1070
     * @return Message
1071
     */
1072
    public function sendInvoice(
1073
        $chatId,
1074
        $title,
1075
        $description,
1076
        $payload,
1077
        $providerToken,
1078
        $startParameter,
1079
        $currency,
1080
        $prices,
1081
        $isFlexible = false,
1082
        $photoUrl = null,
1083
        $photoSize = null,
1084
        $photoWidth = null,
1085
        $photoHeight = null,
1086
        $needName = false,
1087
        $needPhoneNumber = false,
1088
        $needEmail = false,
1089
        $needShippingAddress = false,
1090
        $replyToMessageId = null,
1091
        $replyMarkup = null,
1092
        $disableNotification = false
1093
    ) {
1094
        return Message::fromResponse($this->call('sendInvoice', [
1095
            'chat_id' => $chatId,
1096
            'title' => $title,
1097
            'description' => $description,
1098
            'payload' => $payload,
1099
            'provider_token' => $providerToken,
1100
            'start_parameter' => $startParameter,
1101
            'currency' => $currency,
1102
            'prices' => json_encode($prices),
1103
            'is_flexible' => $isFlexible,
1104
            'photo_url' => $photoUrl,
1105
            'photo_size' => $photoSize,
1106
            'photo_width' => $photoWidth,
1107
            'photo_height' => $photoHeight,
1108
            'need_name' => $needName,
1109
            'need_phone_number' => $needPhoneNumber,
1110
            'need_email' => $needEmail,
1111
            'need_shipping_address' => $needShippingAddress,
1112
            'reply_to_message_id' => $replyToMessageId,
1113
            'reply_markup' => is_null($replyMarkup) ? $replyMarkup : $replyMarkup->toJson(),
1114
            'disable_notification' => (bool)$disableNotification,
1115
        ]));
1116
    }
1117
1118
    /**
1119
     * If you sent an invoice requesting a shipping address and the parameter is_flexible was specified, the Bot API
1120
     * will send an Update with a shipping_query field to the bot. Use this method to reply to shipping queries.
1121
     * On success, True is returned.
1122
     *
1123
     * @param string $shippingQueryId
1124
     * @param bool $ok
1125
     * @param array $shipping_options
1126
     * @param null|string $errorMessage
1127
     *
1128
     * @return bool
1129
     *
1130
     */
1131
    public function answerShippingQuery($shippingQueryId, $ok = true, $shipping_options = [], $errorMessage = null)
1132
    {
1133
        return $this->call('answerShippingQuery', [
1134
            'shipping_query_id' => $shippingQueryId,
1135
            'ok' => (bool)$ok,
1136
            'shipping_options' => json_encode($shipping_options),
1137
            'error_message' => $errorMessage
1138
        ]);
1139
    }
1140
1141
    /**
1142
     * Use this method to respond to such pre-checkout queries. On success, True is returned.
1143
     * Note: The Bot API must receive an answer within 10 seconds after the pre-checkout query was sent.
1144
     *
1145
     * @param string $preCheckoutQueryId
1146
     * @param bool $ok
1147
     * @param null|string $errorMessage
1148
     *
1149
     * @return mixed
1150
     */
1151
    public function answerPreCheckoutQuery($preCheckoutQueryId, $ok = true, $errorMessage = null)
1152
    {
1153
        return $this->call('answerPreCheckoutQuery', [
1154
            'pre_checkout_query_id' => $preCheckoutQueryId,
1155
            'ok' => (bool)$ok,
1156
            'error_message' => $errorMessage
1157
        ]);
1158
    }
1159
}
1160