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