Completed
Push — bot_api_3.0 ( efc501...2fd8c0 )
by Armando
02:41
created

Request::sendVideoNote()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 3
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
crap 2
1
<?php
2
/**
3
 * This file is part of the TelegramBot package.
4
 *
5
 * (c) Avtandil Kikabidze aka LONGMAN <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Longman\TelegramBot;
12
13
use GuzzleHttp\Client;
14
use GuzzleHttp\Exception\RequestException;
15
use Longman\TelegramBot\Entities\File;
16
use Longman\TelegramBot\Entities\ServerResponse;
17
use Longman\TelegramBot\Exception\TelegramException;
18
19
class Request
20
{
21
    /**
22
     * Telegram object
23
     *
24
     * @var \Longman\TelegramBot\Telegram
25
     */
26
    private static $telegram;
27
28
    /**
29
     * URI of the Telegram API
30
     *
31
     * @var string
32
     */
33
    private static $api_base_uri = 'https://api.telegram.org';
34
35
    /**
36
     * Guzzle Client object
37
     *
38
     * @var \GuzzleHttp\Client
39
     */
40
    private static $client;
41
42
    /**
43
     * Input value of the request
44
     *
45
     * @var string
46
     */
47
    private static $input;
48
49
    /**
50
     * Request limiter
51
     *
52
     * @var boolean
53
     */
54
    private static $limiter_enabled;
55
56
    /**
57
     * Request limiter's interval between checks
58
     *
59
     * @var boolean
60
     */
61
    private static $limiter_interval;
62
63
    /**
64
     * Available actions to send
65
     *
66
     * @var array
67
     */
68
    private static $actions = [
69
        'getUpdates',
70
        'setWebhook',
71
        'deleteWebhook',
72
        'getMe',
73
        'sendMessage',
74
        'forwardMessage',
75
        'sendPhoto',
76
        'sendAudio',
77
        'sendDocument',
78
        'sendSticker',
79
        'sendVideo',
80
        'sendVoice',
81
        'sendLocation',
82
        'sendVenue',
83
        'sendContact',
84
        'sendInvoice',
85
        'sendChatAction',
86
        'getUserProfilePhotos',
87
        'getFile',
88
        'kickChatMember',
89
        'leaveChat',
90
        'unbanChatMember',
91
        'getChat',
92
        'getChatAdministrators',
93
        'getChatMember',
94
        'getChatMembersCount',
95
        'answerCallbackQuery',
96
        'answerInlineQuery',
97
        'answerShippingQuery',
98
        'answerPreCheckoutQuery',
99
        'editMessageText',
100
        'editMessageCaption',
101
        'editMessageReplyMarkup',
102
        'getWebhookInfo',
103
        'deleteMessage',
104
    ];
105
106
    /**
107
     * Initialize
108
     *
109
     * @param \Longman\TelegramBot\Telegram $telegram
110
     *
111
     * @throws TelegramException
112
     */
113 30
    public static function initialize(Telegram $telegram)
114
    {
115 30
        if (!($telegram instanceof Telegram)) {
116
            throw new TelegramException('Invalid Telegram pointer!');
117
        }
118
119 30
        self::$telegram = $telegram;
120 30
        self::setClient(new Client(['base_uri' => self::$api_base_uri]));
121 30
    }
122
123
    /**
124
     * Set a custom Guzzle HTTP Client object
125
     *
126
     * @param Client $client
127
     *
128
     * @throws TelegramException
129
     */
130 30
    public static function setClient(Client $client)
131
    {
132 30
        if (!($client instanceof Client)) {
133
            throw new TelegramException('Invalid GuzzleHttp\Client pointer!');
134
        }
135
136 30
        self::$client = $client;
137 30
    }
138
139
    /**
140
     * Set input from custom input or stdin and return it
141
     *
142
     * @return string
143
     * @throws \Longman\TelegramBot\Exception\TelegramException
144
     */
145
    public static function getInput()
146
    {
147
        // First check if a custom input has been set, else get the PHP input.
148
        if (!($input = self::$telegram->getCustomInput())) {
149
            $input = file_get_contents('php://input');
150
        }
151
152
        // Make sure we have a string to work with.
153
        if (is_string($input)) {
154
            self::$input = $input;
155
        } else {
156
            throw new TelegramException('Input must be a string!');
157
        }
158
159
        TelegramLog::update(self::$input);
160
161
        return self::$input;
162
    }
163
164
    /**
165
     * Generate general fake server response
166
     *
167
     * @param array $data Data to add to fake response
168
     *
169
     * @return array Fake response data
170
     */
171 1
    public static function generateGeneralFakeServerResponse(array $data = [])
172
    {
173
        //PARAM BINDED IN PHPUNIT TEST FOR TestServerResponse.php
174
        //Maybe this is not the best possible implementation
175
176
        //No value set in $data ie testing setWebhook
177
        //Provided $data['chat_id'] ie testing sendMessage
178
179 1
        $fake_response = ['ok' => true]; // :)
180
181 1
        if ($data === []) {
182 1
            $fake_response['result'] = true;
183
        }
184
185
        //some data to let iniatilize the class method SendMessage
186 1
        if (isset($data['chat_id'])) {
187 1
            $data['message_id'] = '1234';
188 1
            $data['date']       = '1441378360';
189 1
            $data['from']       = [
190
                'id'         => 123456789,
191
                'first_name' => 'botname',
192
                'username'   => 'namebot',
193
            ];
194 1
            $data['chat']       = ['id' => $data['chat_id']];
195
196 1
            $fake_response['result'] = $data;
197
        }
198
199 1
        return $fake_response;
200
    }
201
202
    /**
203
     * Properly set up the request params
204
     *
205
     * If any item of the array is a resource, reformat it to a multipart request.
206
     * Else, just return the passed data as form params.
207
     *
208
     * @param array $data
209
     *
210
     * @return array
211
     */
212
    private static function setUpRequestParams(array $data)
213
    {
214
        $has_resource = false;
215
        $multipart = [];
216
217
        // Convert any nested arrays into JSON strings.
218
        array_walk($data, function (&$item) {
219
            is_array($item) && $item = json_encode($item);
220
        });
221
222
        //Reformat data array in multipart way if it contains a resource
223
        foreach ($data as $key => $item) {
224
            $has_resource |= (is_resource($item) || $item instanceof \GuzzleHttp\Psr7\Stream);
225
            $multipart[] = ['name' => $key, 'contents' => $item];
226
        }
227
        if ($has_resource) {
228
            return ['multipart' => $multipart];
229
        }
230
231
        return ['form_params' => $data];
232
    }
233
234
    /**
235
     * Execute HTTP Request
236
     *
237
     * @param string $action Action to execute
238
     * @param array  $data   Data to attach to the execution
239
     *
240
     * @return string Result of the HTTP Request
241
     * @throws \Longman\TelegramBot\Exception\TelegramException
242
     */
243
    public static function execute($action, array $data = [])
244
    {
245
        //Fix so that the keyboard markup is a string, not an object
246
        if (isset($data['reply_markup'])) {
247
            $data['reply_markup'] = json_encode($data['reply_markup']);
248
        }
249
250
        $result = null;
251
        $request_params = self::setUpRequestParams($data);
252
        $request_params['debug'] = TelegramLog::getDebugLogTempStream();
253
254
        try {
255
            $response = self::$client->post(
256
                '/bot' . self::$telegram->getApiKey() . '/' . $action,
257
                $request_params
258
            );
259
            $result = (string) $response->getBody();
260
261
            //Logging getUpdates Update
262
            if ($action === 'getUpdates') {
263
                TelegramLog::update($result);
264
            }
265
        } catch (RequestException $e) {
266
            $result = ($e->getResponse()) ? (string) $e->getResponse()->getBody() : '';
267
        } finally {
268
            //Logging verbose debug output
269
            TelegramLog::endDebugLogTempStream('Verbose HTTP Request output:' . PHP_EOL . '%s' . PHP_EOL);
270
        }
271
272
        return $result;
273
    }
274
275
    /**
276
     * Download file
277
     *
278
     * @param \Longman\TelegramBot\Entities\File $file
279
     *
280
     * @return boolean
281
     * @throws \Longman\TelegramBot\Exception\TelegramException
282
     */
283
    public static function downloadFile(File $file)
284
    {
285
        if (empty($download_path = self::$telegram->getDownloadPath())) {
286
            throw new TelegramException('Download path not set!');
287
        }
288
289
        $tg_file_path = $file->getFilePath();
290
        $file_path    = $download_path . '/' . $tg_file_path;
291
292
        $file_dir = dirname($file_path);
293
        //For safety reasons, first try to create the directory, then check that it exists.
294
        //This is in case some other process has created the folder in the meantime.
295
        if (!@mkdir($file_dir, 0755, true) && !is_dir($file_dir)) {
296
            throw new TelegramException('Directory ' . $file_dir . ' can\'t be created');
297
        }
298
299
        $debug_handle = TelegramLog::getDebugLogTempStream();
300
301
        try {
302
            self::$client->get(
303
                '/file/bot' . self::$telegram->getApiKey() . '/' . $tg_file_path,
304
                ['debug' => $debug_handle, 'sink' => $file_path]
305
            );
306
307
            return filesize($file_path) > 0;
308
        } catch (RequestException $e) {
309
            return ($e->getResponse()) ? (string) $e->getResponse()->getBody() : '';
310
        } finally {
311
            //Logging verbose debug output
312
            TelegramLog::endDebugLogTempStream('Verbose HTTP File Download Request output:' . PHP_EOL . '%s' . PHP_EOL);
313
        }
314
    }
315
316
    /**
317
     * Encode file
318
     *
319
     * @param string $file
320
     *
321
     * @return resource
322
     * @throws \Longman\TelegramBot\Exception\TelegramException
323
     */
324
    protected static function encodeFile($file)
325
    {
326
        $fp = fopen($file, 'r');
327
        if ($fp === false) {
328
            throw new TelegramException('Cannot open "' . $file . '" for reading');
329
        }
330
331
        return $fp;
332
    }
333
334
    /**
335
     * Send command
336
     *
337
     * @todo Fake response doesn't need json encoding?
338
     *
339
     * @param string $action
340
     * @param array  $data
341
     *
342
     * @return \Longman\TelegramBot\Entities\ServerResponse
343
     * @throws \Longman\TelegramBot\Exception\TelegramException
344
     */
345
    public static function send($action, array $data = [])
346
    {
347
        self::ensureValidAction($action);
348
349
        $bot_username = self::$telegram->getBotUsername();
350
351
        if (defined('PHPUNIT_TESTSUITE')) {
352
            $fake_response = self::generateGeneralFakeServerResponse($data);
353
354
            return new ServerResponse($fake_response, $bot_username);
355
        }
356
357
        self::ensureNonEmptyData($data);
358
359
        self::limitTelegramRequests($action, $data);
360
361
        $response = json_decode(self::execute($action, $data), true);
362
363
        if (null === $response) {
364
            throw new TelegramException('Telegram returned an invalid response! Please review your bot name and API key.');
365
        }
366
367
        return new ServerResponse($response, $bot_username);
368
    }
369
370
    /**
371
     * Make sure the data isn't empty, else throw an exception
372
     *
373
     * @param array $data
374
     *
375
     * @throws \Longman\TelegramBot\Exception\TelegramException
376
     */
377
    private static function ensureNonEmptyData(array $data)
378
    {
379
        if (count($data) === 0) {
380
            throw new TelegramException('Data is empty!');
381
        }
382
    }
383
384
    /**
385
     * Make sure the action is valid, else throw an exception
386
     *
387
     * @param string $action
388
     *
389
     * @throws \Longman\TelegramBot\Exception\TelegramException
390
     */
391
    private static function ensureValidAction($action)
392
    {
393
        if (!in_array($action, self::$actions, true)) {
394
            throw new TelegramException('The action "' . $action . '" doesn\'t exist!');
395
        }
396
    }
397
398
    /**
399
     * Assign an encoded file to a data array
400
     *
401
     * @param array  $data
402
     * @param string $field
403
     * @param string $file
404
     *
405
     * @throws \Longman\TelegramBot\Exception\TelegramException
406
     */
407
    private static function assignEncodedFile(&$data, $field, $file)
408
    {
409
        if ($file !== null && $file !== '') {
410
            $data[$field] = self::encodeFile($file);
411
        }
412
    }
413
414
    /**
415
     * Returns basic information about the bot in form of a User object
416
     *
417
     * @link https://core.telegram.org/bots/api#getme
418
     *
419
     * @return \Longman\TelegramBot\Entities\ServerResponse
420
     * @throws \Longman\TelegramBot\Exception\TelegramException
421
     */
422
    public static function getMe()
423
    {
424
        // Added fake parameter, because of some cURL version failed POST request without parameters
425
        // see https://github.com/php-telegram-bot/core/pull/228
426
        return self::send('getMe', ['whoami']);
427
    }
428
429
    /**
430
     * Use this method to send text messages. On success, the sent Message is returned
431
     *
432
     * @link https://core.telegram.org/bots/api#sendmessage
433
     *
434
     * @param array $data
435
     *
436
     * @return \Longman\TelegramBot\Entities\ServerResponse
437
     * @throws \Longman\TelegramBot\Exception\TelegramException
438
     */
439
    public static function sendMessage(array $data)
440
    {
441
        $text = $data['text'];
442
443
        do {
444
            //Chop off and send the first message
445
            $data['text'] = mb_substr($text, 0, 4096);
446
            $response     = self::send('sendMessage', $data);
447
448
            //Prepare the next message
449
            $text = mb_substr($text, 4096);
450
        } while (mb_strlen($text, 'UTF-8') > 0);
451
452
        return $response;
453
    }
454
455
    /**
456
     * Use this method to forward messages of any kind. On success, the sent Message is returned
457
     *
458
     * @link https://core.telegram.org/bots/api#forwardmessage
459
     *
460
     * @param array $data
461
     *
462
     * @return \Longman\TelegramBot\Entities\ServerResponse
463
     * @throws \Longman\TelegramBot\Exception\TelegramException
464
     */
465
    public static function forwardMessage(array $data)
466
    {
467
        return self::send('forwardMessage', $data);
468
    }
469
470
    /**
471
     * Use this method to send photos. On success, the sent Message is returned
472
     *
473
     * @link https://core.telegram.org/bots/api#sendphoto
474
     *
475
     * @param array  $data
476
     * @param string $file
477
     *
478
     * @return \Longman\TelegramBot\Entities\ServerResponse
479
     * @throws \Longman\TelegramBot\Exception\TelegramException
480
     */
481
    public static function sendPhoto(array $data, $file = null)
482
    {
483
        self::assignEncodedFile($data, 'photo', $file);
484
485
        return self::send('sendPhoto', $data);
486
    }
487
488
    /**
489
     * Use this method to send audio files
490
     *
491
     * Your audio must be in the .mp3 format. On success, the sent Message is returned.
492
     * Bots can currently send audio files of up to 50 MB in size, this limit may be changed in the future.
493
     * For sending voice messages, use the sendVoice method instead.
494
     *
495
     * @link https://core.telegram.org/bots/api#sendaudio
496
     *
497
     * @param array  $data
498
     * @param string $file
499
     *
500
     * @return \Longman\TelegramBot\Entities\ServerResponse
501
     * @throws \Longman\TelegramBot\Exception\TelegramException
502
     */
503
    public static function sendAudio(array $data, $file = null)
504
    {
505
        self::assignEncodedFile($data, 'audio', $file);
506
507
        return self::send('sendAudio', $data);
508
    }
509
510
    /**
511
     * Use this method to send general files. On success, the sent Message is returned.
512
     *
513
     * Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future.
514
     *
515
     * @link https://core.telegram.org/bots/api#senddocument
516
     *
517
     * @param array  $data
518
     * @param string $file
519
     *
520
     * @return \Longman\TelegramBot\Entities\ServerResponse
521
     * @throws \Longman\TelegramBot\Exception\TelegramException
522
     */
523
    public static function sendDocument(array $data, $file = null)
524
    {
525
        self::assignEncodedFile($data, 'document', $file);
526
527
        return self::send('sendDocument', $data);
528
    }
529
530
    /**
531
     * Use this method to send .webp stickers. On success, the sent Message is returned.
532
     *
533
     * @link https://core.telegram.org/bots/api#sendsticker
534
     *
535
     * @param array  $data
536
     * @param string $file
537
     *
538
     * @return \Longman\TelegramBot\Entities\ServerResponse
539
     * @throws \Longman\TelegramBot\Exception\TelegramException
540
     */
541
    public static function sendSticker(array $data, $file = null)
542
    {
543
        self::assignEncodedFile($data, 'sticker', $file);
544
545
        return self::send('sendSticker', $data);
546
    }
547
548
    /**
549
     * Use this method to send video files. On success, the sent Message is returned.
550
     *
551
     * Telegram clients support mp4 videos (other formats may be sent as Document).
552
     * Bots can currently send video files of up to 50 MB in size, this limit may be changed in the future.
553
     *
554
     * @link https://core.telegram.org/bots/api#sendvideo
555
     *
556
     * @param array  $data
557
     * @param string $file
558
     *
559
     * @return \Longman\TelegramBot\Entities\ServerResponse
560
     * @throws \Longman\TelegramBot\Exception\TelegramException
561
     */
562
    public static function sendVideo(array $data, $file = null)
563
    {
564
        self::assignEncodedFile($data, 'video', $file);
565
566
        return self::send('sendVideo', $data);
567
    }
568
569
    /**
570
     * Use this method to send audio files. On success, the sent Message is returned.
571
     *
572
     * Telegram clients will display the file as a playable voice message.
573
     * For this to work, your audio must be in an .ogg file encoded with OPUS (other formats may be sent as Audio or Document).
574
     * Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future.
575
     *
576
     * @link https://core.telegram.org/bots/api#sendvoice
577
     *
578
     * @param array  $data
579
     * @param string $file
580
     *
581
     * @return \Longman\TelegramBot\Entities\ServerResponse
582
     * @throws \Longman\TelegramBot\Exception\TelegramException
583
     */
584
    public static function sendVoice(array $data, $file = null)
585
    {
586
        self::assignEncodedFile($data, 'voice', $file);
587
588
        return self::send('sendVoice', $data);
589
    }
590
591
    /**
592
     * Use this method to send point on the map. On success, the sent Message is returned.
593
     *
594
     * @link https://core.telegram.org/bots/api#sendlocation
595
     *
596
     * @param array $data
597
     *
598
     * @return \Longman\TelegramBot\Entities\ServerResponse
599
     * @throws \Longman\TelegramBot\Exception\TelegramException
600
     */
601
    public static function sendLocation(array $data)
602
    {
603
        return self::send('sendLocation', $data);
604
    }
605
606
    /**
607
     * Use this method to send information about a venue. On success, the sent Message is returned.
608
     *
609
     * @link https://core.telegram.org/bots/api#sendvenue
610
     *
611
     * @param array $data
612
     *
613
     * @return \Longman\TelegramBot\Entities\ServerResponse
614
     * @throws \Longman\TelegramBot\Exception\TelegramException
615
     */
616
    public static function sendVenue(array $data)
617
    {
618
        return self::send('sendVenue', $data);
619
    }
620
621
    /**
622
     * Use this method to send phone contacts. On success, the sent Message is returned.
623
     *
624
     * @link https://core.telegram.org/bots/api#sendcontact
625
     *
626
     * @param array $data
627
     *
628
     * @return \Longman\TelegramBot\Entities\ServerResponse
629
     * @throws \Longman\TelegramBot\Exception\TelegramException
630
     */
631
    public static function sendContact(array $data)
632
    {
633
        return self::send('sendContact', $data);
634
    }
635
636
    /**
637
     * Use this method to send invoices.
638
     *
639
     * On success, the sent Message is returned.
640
     *
641
     * @link https://core.telegram.org/bots/api#sendinvoice
642
     *
643
     * @param array $data
644
     *
645
     * @return \Longman\TelegramBot\Entities\ServerResponse
646
     * @throws \Longman\TelegramBot\Exception\TelegramException
647
     */
648
    public static function sendInvoice(array $data)
649
    {
650
        return self::send('sendInvoice', $data);
651
    }
652
653
    /**
654
     * Use this method when you need to tell the user that something is happening on the bot's side.
655
     *
656
     * The status is set for 5 seconds or less.
657
     * (when a message arrives from your bot, Telegram clients clear its typing status)
658
     *
659
     * @link https://core.telegram.org/bots/api#sendchataction
660
     *
661
     * @param array $data
662
     *
663
     * @return \Longman\TelegramBot\Entities\ServerResponse
664
     * @throws \Longman\TelegramBot\Exception\TelegramException
665
     */
666
    public static function sendChatAction(array $data)
667
    {
668
        return self::send('sendChatAction', $data);
669
    }
670
671
    /**
672
     * Use this method to get a list of profile pictures for a user. Returns a UserProfilePhotos object.
673
     *
674
     * @param array $data
675
     *
676
     * @return \Longman\TelegramBot\Entities\ServerResponse
677
     * @throws \Longman\TelegramBot\Exception\TelegramException
678
     */
679
    public static function getUserProfilePhotos(array $data)
680
    {
681
        return self::send('getUserProfilePhotos', $data);
682
    }
683
684
    /**
685
     * Use this method to get basic info about a file and prepare it for downloading. On success, a File object is returned.
686
     *
687
     * For the moment, bots can download files of up to 20MB in size.
688
     * The file can then be downloaded via the link https://api.telegram.org/file/bot<token>/<file_path>,
689
     * where <file_path> is taken from the response.
690
     * It is guaranteed that the link will be valid for at least 1 hour.
691
     * When the link expires, a new one can be requested by calling getFile again.
692
     *
693
     * @link https://core.telegram.org/bots/api#getfile
694
     *
695
     * @param array $data
696
     *
697
     * @return \Longman\TelegramBot\Entities\ServerResponse
698
     * @throws \Longman\TelegramBot\Exception\TelegramException
699
     */
700
    public static function getFile(array $data)
701
    {
702
        return self::send('getFile', $data);
703
    }
704
705
    /**
706
     * Use this method to kick a user from a group or a supergroup. Returns True on success.
707
     *
708
     * In the case of supergroups, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first.
709
     * The bot must be an administrator in the group for this to work.
710
     *
711
     * @link https://core.telegram.org/bots/api#kickchatmember
712
     *
713
     * @param array $data
714
     *
715
     * @return \Longman\TelegramBot\Entities\ServerResponse
716
     * @throws \Longman\TelegramBot\Exception\TelegramException
717
     */
718
    public static function kickChatMember(array $data)
719
    {
720
        return self::send('kickChatMember', $data);
721
    }
722
723
    /**
724
     * Use this method for your bot to leave a group, supergroup or channel. Returns True on success.
725
     *
726
     * @link https://core.telegram.org/bots/api#leavechat
727
     *
728
     * @param array $data
729
     *
730
     * @return \Longman\TelegramBot\Entities\ServerResponse
731
     * @throws \Longman\TelegramBot\Exception\TelegramException
732
     */
733
    public static function leaveChat(array $data)
734
    {
735
        return self::send('leaveChat', $data);
736
    }
737
738
    /**
739
     * Use this method to unban a previously kicked user in a supergroup. Returns True on success.
740
     *
741
     * The user will not return to the group automatically, but will be able to join via link, etc.
742
     * The bot must be an administrator in the group for this to work.
743
     *
744
     * @link https://core.telegram.org/bots/api#unbanchatmember
745
     *
746
     * @param array $data
747
     *
748
     * @return \Longman\TelegramBot\Entities\ServerResponse
749
     * @throws \Longman\TelegramBot\Exception\TelegramException
750
     */
751
    public static function unbanChatMember(array $data)
752
    {
753
        return self::send('unbanChatMember', $data);
754
    }
755
756
    /**
757
     * Use this method to get up to date information about the chat (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.). Returns a Chat object on success.
758
     *
759
     * @todo add get response in ServerResponse.php?
760
     *
761
     * @link https://core.telegram.org/bots/api#getchat
762
     *
763
     * @param array $data
764
     *
765
     * @return \Longman\TelegramBot\Entities\ServerResponse
766
     * @throws \Longman\TelegramBot\Exception\TelegramException
767
     */
768
    public static function getChat(array $data)
769
    {
770
        return self::send('getChat', $data);
771
    }
772
773
    /**
774
     * Use this method to get a list of administrators in a chat.
775
     *
776
     * On success, returns an Array of ChatMember objects that contains information about all chat administrators except other bots.
777
     * If the chat is a group or a supergroup and no administrators were appointed, only the creator will be returned.
778
     *
779
     * @todo add get response in ServerResponse.php?
780
     *
781
     * @link https://core.telegram.org/bots/api#getchatadministrators
782
     *
783
     * @param array $data
784
     *
785
     * @return \Longman\TelegramBot\Entities\ServerResponse
786
     * @throws \Longman\TelegramBot\Exception\TelegramException
787
     */
788
    public static function getChatAdministrators(array $data)
789
    {
790
        return self::send('getChatAdministrators', $data);
791
    }
792
793
    /**
794
     * Use this method to get the number of members in a chat. Returns Int on success.
795
     *
796
     * @todo add get response in ServerResponse.php?
797
     *
798
     * @link https://core.telegram.org/bots/api#getchatmemberscount
799
     *
800
     * @param array $data
801
     *
802
     * @return \Longman\TelegramBot\Entities\ServerResponse
803
     * @throws \Longman\TelegramBot\Exception\TelegramException
804
     */
805
    public static function getChatMembersCount(array $data)
806
    {
807
        return self::send('getChatMembersCount', $data);
808
    }
809
810
    /**
811
     * Use this method to get information about a member of a chat. Returns a ChatMember object on success.
812
     *
813
     * @todo add get response in ServerResponse.php?
814
     *
815
     * @link https://core.telegram.org/bots/api#getchatmember
816
     *
817
     * @param array $data
818
     *
819
     * @return \Longman\TelegramBot\Entities\ServerResponse
820
     * @throws \Longman\TelegramBot\Exception\TelegramException
821
     */
822
    public static function getChatMember(array $data)
823
    {
824
        return self::send('getChatMember', $data);
825
    }
826
827
    /**
828
     * Use this method to send answers to callback queries sent from inline keyboards. On success, True is returned.
829
     *
830
     * The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.
831
     *
832
     * @link https://core.telegram.org/bots/api#answercallbackquery
833
     *
834
     * @param array $data
835
     *
836
     * @return \Longman\TelegramBot\Entities\ServerResponse
837
     * @throws \Longman\TelegramBot\Exception\TelegramException
838
     */
839
    public static function answerCallbackQuery(array $data)
840
    {
841
        return self::send('answerCallbackQuery', $data);
842
    }
843
844
    /**
845
     * Get updates
846
     *
847
     * @link https://core.telegram.org/bots/api#getupdates
848
     *
849
     * @param array $data
850
     *
851
     * @return \Longman\TelegramBot\Entities\ServerResponse
852
     * @throws \Longman\TelegramBot\Exception\TelegramException
853
     */
854
    public static function getUpdates(array $data)
855
    {
856
        return self::send('getUpdates', $data);
857
    }
858
859
    /**
860
     * Set webhook
861
     *
862
     * @link https://core.telegram.org/bots/api#setwebhook
863
     *
864
     * @param string $url
865
     * @param array  $data Optional parameters.
866
     *
867
     * @return \Longman\TelegramBot\Entities\ServerResponse
868
     * @throws \Longman\TelegramBot\Exception\TelegramException
869
     */
870
    public static function setWebhook($url = '', array $data = [])
871
    {
872
        $data        = array_intersect_key($data, array_flip([
873
            'certificate',
874
            'max_connections',
875
            'allowed_updates',
876
        ]));
877
        $data['url'] = $url;
878
879
        if (isset($data['certificate'])) {
880
            self::assignEncodedFile($data, 'certificate', $data['certificate']);
881
        }
882
883
        return self::send('setWebhook', $data);
884
    }
885
886
    /**
887
     * Delete webhook
888
     *
889
     * @link https://core.telegram.org/bots/api#deletewebhook
890
     *
891
     * @return \Longman\TelegramBot\Entities\ServerResponse
892
     * @throws \Longman\TelegramBot\Exception\TelegramException
893
     */
894
    public static function deleteWebhook()
895
    {
896
        // Must send some arbitrary data for this to work for now...
897
        return self::send('deleteWebhook', ['delete']);
898
    }
899
900
    /**
901
     * Use this method to edit text and game messages sent by the bot or via the bot (for inline bots).
902
     *
903
     * On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned.
904
     *
905
     * @link https://core.telegram.org/bots/api#editmessagetext
906
     *
907
     * @param array $data
908
     *
909
     * @return \Longman\TelegramBot\Entities\ServerResponse
910
     * @throws \Longman\TelegramBot\Exception\TelegramException
911
     */
912
    public static function editMessageText(array $data)
913
    {
914
        return self::send('editMessageText', $data);
915
    }
916
917
    /**
918
     * Use this method to edit captions of messages sent by the bot or via the bot (for inline bots).
919
     *
920
     * On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned.
921
     *
922
     * @link https://core.telegram.org/bots/api#editmessagecaption
923
     *
924
     * @param array $data
925
     *
926
     * @return \Longman\TelegramBot\Entities\ServerResponse
927
     * @throws \Longman\TelegramBot\Exception\TelegramException
928
     */
929
    public static function editMessageCaption(array $data)
930
    {
931
        return self::send('editMessageCaption', $data);
932
    }
933
934
    /**
935
     * Use this method to edit only the reply markup of messages sent by the bot or via the bot (for inline bots).
936
     *
937
     * On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned.
938
     *
939
     * @link https://core.telegram.org/bots/api#editmessagereplymarkup
940
     *
941
     * @param array $data
942
     *
943
     * @return \Longman\TelegramBot\Entities\ServerResponse
944
     * @throws \Longman\TelegramBot\Exception\TelegramException
945
     */
946
    public static function editMessageReplyMarkup(array $data)
947
    {
948
        return self::send('editMessageReplyMarkup', $data);
949
    }
950
951
    /**
952
     * Use this method to send answers to an inline query. On success, True is returned.
953
     *
954
     * No more than 50 results per query are allowed.
955
     *
956
     * @link https://core.telegram.org/bots/api#answerinlinequery
957
     *
958
     * @param array $data
959
     *
960
     * @return \Longman\TelegramBot\Entities\ServerResponse
961
     * @throws \Longman\TelegramBot\Exception\TelegramException
962
     */
963
    public static function answerInlineQuery(array $data)
964
    {
965
        return self::send('answerInlineQuery', $data);
966
    }
967
968
    /**
969
     * Use this method to reply to shipping queries.
970
     *
971
     * If you sent an invoice requesting a shipping address and the parameter is_flexible was specified, the Bot API will send an Update with a shipping_query field to the bot.
972
     * On success, True is returned.
973
     *
974
     * @link https://core.telegram.org/bots/api#answershippingquery
975
     *
976
     * @param array $data
977
     *
978
     * @return \Longman\TelegramBot\Entities\ServerResponse
979
     * @throws \Longman\TelegramBot\Exception\TelegramException
980
     */
981
    public static function answerShippingQuery(array $data)
982
    {
983
        return self::send('answerShippingQuery', $data);
984
    }
985
986
    /**
987
     * Use this method to respond to pre-checkout queries.
988
     *
989
     * Once the user has confirmed their payment and shipping details, the Bot API sends the final confirmation in the form of an Update with the field pre_checkout_query.
990
     * On success, True is returned.
991
     *
992
     * Note: The Bot API must receive an answer within 10 seconds after the pre-checkout query was sent.
993
     *
994
     * @link https://core.telegram.org/bots/api#answerprecheckoutquery
995
     *
996
     * @param array $data
997
     *
998
     * @return \Longman\TelegramBot\Entities\ServerResponse
999
     * @throws \Longman\TelegramBot\Exception\TelegramException
1000
     */
1001
    public static function answerPreCheckoutQuery(array $data)
1002
    {
1003
        return self::send('answerPreCheckoutQuery', $data);
1004
    }
1005
1006
    /**
1007
     * Return an empty Server Response
1008
     *
1009
     * No request to telegram are sent, this function is used in commands that
1010
     * don't need to fire a message after execution
1011
     *
1012
     * @return \Longman\TelegramBot\Entities\ServerResponse
1013
     * @throws \Longman\TelegramBot\Exception\TelegramException
1014
     */
1015
    public static function emptyResponse()
1016
    {
1017
        return new ServerResponse(['ok' => true, 'result' => true], null);
1018
    }
1019
1020
    /**
1021
     * Send message to all active chats
1022
     *
1023
     * @param string $callback_function
1024
     * @param array  $data
1025
     * @param array  $select_chats_params
1026
     *
1027
     * @return array
1028
     * @throws TelegramException
1029
     */
1030
    public static function sendToActiveChats(
1031
        $callback_function,
1032
        array $data,
1033
        array $select_chats_params
1034
    ) {
1035
        $callback_path = __NAMESPACE__ . '\Request';
1036
        if (!method_exists($callback_path, $callback_function)) {
1037
            throw new TelegramException('Method "' . $callback_function . '" not found in class Request.');
1038
        }
1039
1040
        $chats = DB::selectChats($select_chats_params);
1041
1042
        $results = [];
1043
        if (is_array($chats)) {
1044
            foreach ($chats as $row) {
1045
                $data['chat_id'] = $row['chat_id'];
1046
                $results[]       = call_user_func($callback_path . '::' . $callback_function, $data);
1047
            }
1048
        }
1049
1050
        return $results;
1051
    }
1052
1053
    /**
1054
     * Use this method to get current webhook status.
1055
     *
1056
     * @link https://core.telegram.org/bots/api#getwebhookinfo
1057
     *
1058
     * @return Entities\ServerResponse
1059
     * @throws \Longman\TelegramBot\Exception\TelegramException
1060
     */
1061
    public static function getWebhookInfo()
1062
    {
1063
        // Must send some arbitrary data for this to work for now...
1064
        return self::send('getWebhookInfo', ['info']);
1065
    }
1066
1067
    /**
1068
     * Enable request limiter
1069
     *
1070
     * @param boolean $value
1071
     * @param array   $options
1072
     *
1073
     * @throws \Longman\TelegramBot\Exception\TelegramException
1074
     */
1075
    public static function setLimiter($value = true, array $options = [])
1076
    {
1077
        if (DB::isDbConnected()) {
1078
            $options_default = [
1079
                'interval' => 1,
1080
            ];
1081
1082
            $options = array_merge($options_default, $options);
1083
1084
            if (!is_numeric($options['interval']) || $options['interval'] <= 0) {
1085
                throw new TelegramException('Interval must be a number and must be greater than zero!');
1086
            }
1087
1088
            self::$limiter_interval = $options['interval'];
0 ignored issues
show
Documentation Bug introduced by
It seems like $options['interval'] of type integer or double or string is incompatible with the declared type boolean of property $limiter_interval.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1089
            self::$limiter_enabled = $value;
1090
        }
1091
    }
1092
1093
    /**
1094
     * This functions delays API requests to prevent reaching Telegram API limits
1095
     *  Can be disabled while in execution by 'Request::setLimiter(false)'
1096
     *
1097
     * @link https://core.telegram.org/bots/faq#my-bot-is-hitting-limits-how-do-i-avoid-this
1098
     *
1099
     * @param string $action
1100
     * @param array  $data
1101
     *
1102
     * @throws \Longman\TelegramBot\Exception\TelegramException
1103
     */
1104
    private static function limitTelegramRequests($action, array $data = [])
1105
    {
1106
        if (self::$limiter_enabled) {
1107
            $limited_methods = [
1108
                'sendMessage',
1109
                'forwardMessage',
1110
                'sendPhoto',
1111
                'sendAudio',
1112
                'sendDocument',
1113
                'sendSticker',
1114
                'sendVideo',
1115
                'sendVoice',
1116
                'sendLocation',
1117
                'sendVenue',
1118
                'sendContact',
1119
                'sendInvoice',
1120
                'editMessageText',
1121
                'editMessageCaption',
1122
                'editMessageReplyMarkup',
1123
            ];
1124
1125
            $chat_id = isset($data['chat_id']) ? $data['chat_id'] : null;
1126
            $inline_message_id = isset($data['inline_message_id']) ? $data['inline_message_id'] : null;
1127
1128
            if (($chat_id || $inline_message_id) && in_array($action, $limited_methods)) {
1129
                $timeout = 60;
1130
1131
                while (true) {
1132
                    if ($timeout <= 0) {
1133
                        throw new TelegramException('Timed out while waiting for a request spot!');
1134
                    }
1135
1136
                    $requests = DB::getTelegramRequestCount($chat_id, $inline_message_id);
1137
1138
                    $chat_per_second = ($requests['LIMIT_PER_SEC'] == 0); // No more than one message per second inside a particular chat
1139
                    $global_per_second = ($requests['LIMIT_PER_SEC_ALL'] < 30);    // No more than 30 messages per second to different chats
1140
                    $groups_per_minute = (((is_numeric($chat_id) && $chat_id > 0) || !is_null($inline_message_id)) || ((!is_numeric($chat_id) || $chat_id < 0) && $requests['LIMIT_PER_MINUTE'] < 20));    // No more than 20 messages per minute in groups and channels
1141
1142
                    if ($chat_per_second && $global_per_second && $groups_per_minute) {
1143
                        break;
1144
                    }
1145
1146
                    $timeout--;
1147
                    usleep(self::$limiter_interval * 1000000);
1148
                }
1149
1150
                DB::insertTelegramRequest($action, $data);
1151
            }
1152
        }
1153
    }
1154
1155
    /**
1156
     * Use this method to delete either bot's messages or messages of other users if the bot is admin of the group.
1157
     *
1158
     * On success, true is returned.
1159
     *
1160
     * @link https://core.telegram.org/bots/api#deletemessage
1161
     *
1162
     * @param array $data
1163
     *
1164
     * @return \Longman\TelegramBot\Entities\ServerResponse
1165
     * @throws \Longman\TelegramBot\Exception\TelegramException
1166
     */
1167
    public static function deleteMessage(array $data)
1168
    {
1169
        return self::send('deleteMessage', $data);
1170
    }
1171
1172
    /**
1173
     * Use this method to send video notes. On success, the sent Message is returned.
1174
     *
1175
     * @link https://core.telegram.org/bots/api#sendvideonote
1176
     *
1177
     * @param array  $data
1178
     * @param string $file
1179
     *
1180
     * @return \Longman\TelegramBot\Entities\ServerResponse
1181
     * @throws \Longman\TelegramBot\Exception\TelegramException
1182
     */
1183
    public static function sendVideoNote(array $data, $file = null)
1184
    {
1185
        self::assignEncodedFile($data, 'video_note', $file);
1186
1187
        return self::send('sendVideoNote', $data);
1188
    }
1189
}
1190