Completed
Pull Request — develop (#314)
by
unknown
03:12
created

Request::answerCallbackQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
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
     * Available actions to send
51
     *
52
     * @var array
53
     */
54
    private static $actions = [
55
        'getUpdates',
56
        'setWebhook',
57
        'getMe',
58
        'sendMessage',
59
        'forwardMessage',
60
        'sendPhoto',
61
        'sendAudio',
62
        'sendDocument',
63
        'sendSticker',
64
        'sendVideo',
65
        'sendVoice',
66
        'sendLocation',
67
        'sendVenue',
68
        'sendContact',
69
        'sendChatAction',
70
        'getUserProfilePhotos',
71
        'getFile',
72
        'kickChatMember',
73
        'leaveChat',
74
        'unbanChatMember',
75
        'getChat',
76
        'getChatAdministrators',
77
        'getChatMember',
78
        'getChatMembersCount',
79
        'answerCallbackQuery',
80
        'answerInlineQuery',
81
        'editMessageText',
82
        'editMessageCaption',
83
        'editMessageReplyMarkup',
84
        'getWebhookInfo',
85
    ];
86
87
    /**
88
     * Initialize
89
     *
90
     * @param \Longman\TelegramBot\Telegram $telegram
91
     *
92
     * @throws \Longman\TelegramBot\Exception\TelegramException
93
     */
94 39
    public static function initialize(Telegram $telegram)
95
    {
96 39
        if (is_object($telegram)) {
97 39
            self::$telegram = $telegram;
98 39
            self::$client   = new Client(['base_uri' => self::$api_base_uri]);
99
        } else {
100
            throw new TelegramException('Telegram pointer is empty!');
101
        }
102 39
    }
103
104
    /**
105
     * Set input from custom input or stdin and return it
106
     *
107
     * @return string
108
     * @throws \Longman\TelegramBot\Exception\TelegramException
109
     */
110
    public static function getInput()
111
    {
112
        // First check if a custom input has been set, else get the PHP input.
113
        if (!($input = self::$telegram->getCustomInput())) {
114
            $input = file_get_contents('php://input');
115
        }
116
117
        // Make sure we have a string to work with.
118
        if (is_string($input)) {
119
            self::$input = $input;
120
        } else {
121
            throw new TelegramException('Input must be a string!');
122
        }
123
124
        TelegramLog::update(self::$input);
125
126
        return self::$input;
127
    }
128
129
    /**
130
     * Generate general fake server response
131
     *
132
     * @param array $data Data to add to fake response
133
     *
134
     * @return array Fake response data
135
     */
136 6
    public static function generateGeneralFakeServerResponse(array $data = [])
137
    {
138
        //PARAM BINDED IN PHPUNIT TEST FOR TestServerResponse.php
139
        //Maybe this is not the best possible implementation
140
141
        //No value set in $data ie testing setWebhook
142
        //Provided $data['chat_id'] ie testing sendMessage
143
144 6
        $fake_response = ['ok' => true]; // :)
145
146 6
        if ($data === []) {
147 1
            $fake_response['result'] = true;
148
        }
149
150
        //some data to let iniatilize the class method SendMessage
151 6
        if (isset($data['chat_id'])) {
152 6
            $data['message_id'] = '1234';
153 6
            $data['date']       = '1441378360';
154 6
            $data['from']       = [
155
                'id'         => 123456789,
156
                'first_name' => 'botname',
157
                'username'   => 'namebot',
158
            ];
159 6
            $data['chat']       = ['id' => $data['chat_id']];
160
161 6
            $fake_response['result'] = $data;
162
        }
163
164 6
        return $fake_response;
165
    }
166
167
    /**
168
     * Properly set up the request params
169
     *
170
     * If any item of the array is a resource, reformat it to a multipart request.
171
     * Else, just return the passed data as form params.
172
     *
173
     * @param array $data
174
     *
175
     * @return array
176
     */
177
    private static function setUpRequestParams(array $data)
178
    {
179
        $has_resource = false;
180
        $multipart    = [];
181
182
        //Reformat data array in multipart way if it contains a resource
183
        foreach ($data as $key => $item) {
184
            $has_resource |= is_resource($item);
185
            $multipart[] = ['name' => $key, 'contents' => $item];
186
        }
187
        if ($has_resource) {
188
            return ['multipart' => $multipart];
189
        }
190
191
        return ['form_params' => $data];
192
    }
193
194
    /**
195
     * Execute HTTP Request
196
     *
197
     * @param string $action Action to execute
198
     * @param array  $data   Data to attach to the execution
199
     *
200
     * @return string Result of the HTTP Request
201
     * @throws \Longman\TelegramBot\Exception\TelegramException
202
     */
203
    public static function execute($action, array $data = [])
204
    {
205
        //Fix so that the keyboard markup is a string, not an object
206
        if (isset($data['reply_markup'])) {
207
            $data['reply_markup'] = (string)$data['reply_markup'];
208
        }
209
210
        $request_params = self::setUpRequestParams($data);
211
212
        $debug_handle            = TelegramLog::getDebugLogTempStream();
213
        $request_params['debug'] = $debug_handle;
214
215
        try {
216
            $response = self::$client->post(
217
                '/bot' . self::$telegram->getApiKey() . '/' . $action,
218
                $request_params
219
            );
220
            $result   = (string)$response->getBody();
221
222
            //Logging getUpdates Update
223
            if ($action === 'getUpdates') {
224
                TelegramLog::update($result);
225
            }
226
227
            return $result;
228
        } catch (RequestException $e) {
229
            throw new TelegramException($e->getMessage());
230
        } finally {
231
            //Logging verbose debug output
232
            TelegramLog::endDebugLogTempStream("Verbose HTTP Request output:\n%s\n");
233
        }
234
    }
235
236
    /**
237
     * Download file
238
     *
239
     * @param \Longman\TelegramBot\Entities\File $file
240
     *
241
     * @return boolean
242
     * @throws \Longman\TelegramBot\Exception\TelegramException
243
     */
244
    public static function downloadFile(File $file)
245
    {
246
        $tg_file_path = $file->getFilePath();
247
        $file_path    = self::$telegram->getDownloadPath() . '/' . $tg_file_path;
248
249
        $file_dir = dirname($file_path);
250
        //For safety reasons, first try to create the directory, then check that it exists.
251
        //This is in case some other process has created the folder in the meantime.
252
        if (!@mkdir($file_dir, 0755, true) && !is_dir($file_dir)) {
253
            throw new TelegramException('Directory ' . $file_dir . ' can\'t be created');
254
        }
255
256
        $debug_handle = TelegramLog::getDebugLogTempStream();
257
258
        try {
259
            self::$client->get(
260
                '/file/bot' . self::$telegram->getApiKey() . '/' . $tg_file_path,
261
                ['debug' => $debug_handle, 'sink' => $file_path]
262
            );
263
264
            return filesize($file_path) > 0;
265
        } catch (RequestException $e) {
266
            throw new TelegramException($e->getMessage());
267
        } finally {
268
            //Logging verbose debug output
269
            TelegramLog::endDebugLogTempStream("Verbose HTTP File Download Request output:\n%s\n");
270
        }
271
    }
272
273
    /**
274
     * Encode file
275
     *
276
     * @param string $file
277
     *
278
     * @return resource
279
     * @throws \Longman\TelegramBot\Exception\TelegramException
280
     */
281
    protected static function encodeFile($file)
282
    {
283
        $fp = fopen($file, 'r');
284
        if ($fp === false) {
285
            throw new TelegramException('Cannot open ' . $file . ' for reading');
286
        }
287
288
        return $fp;
289
    }
290
291
    /**
292
     * Send command
293
     *
294
     * @todo Fake response doesn't need json encoding?
295
     *
296
     * @param string $action
297
     * @param array  $data
298
     *
299
     * @return \Longman\TelegramBot\Entities\ServerResponse
300
     * @throws \Longman\TelegramBot\Exception\TelegramException
301
     */
302 5
    public static function send($action, array $data = [])
303
    {
304 5
        self::ensureValidAction($action);
305
306 5
        $bot_name = self::$telegram->getBotName();
307
308 5
        if (defined('PHPUNIT_TESTSUITE')) {
309 5
            $fake_response = self::generateGeneralFakeServerResponse($data);
310
311 5
            return new ServerResponse($fake_response, $bot_name);
312
        }
313
314
        self::ensureNonEmptyData($data);
315
316
        $response = json_decode(self::execute($action, $data), true);
317
318
        if (null === $response) {
319
            throw new TelegramException('Telegram returned an invalid response! Please review your bot name and API key.');
320
        }
321
322
        return new ServerResponse($response, $bot_name);
323
    }
324
325
    /**
326
     * Make sure the data isn't empty, else throw an exception
327
     *
328
     * @param array $data
329
     *
330
     * @throws \Longman\TelegramBot\Exception\TelegramException
331
     */
332
    private static function ensureNonEmptyData(array $data)
333
    {
334
        if (count($data) === 0) {
335
            throw new TelegramException('Data is empty!');
336
        }
337
    }
338
339
    /**
340
     * Make sure the action is valid, else throw an exception
341
     *
342
     * @param string $action
343
     *
344
     * @throws \Longman\TelegramBot\Exception\TelegramException
345
     */
346 5
    private static function ensureValidAction($action)
347
    {
348 5
        if (!in_array($action, self::$actions, true)) {
349
            throw new TelegramException('The action " . $action . " doesn\'t exist!');
350
        }
351 5
    }
352
353
    /**
354
     * Assign an encoded file to a data array
355
     *
356
     * @param array  $data
357
     * @param string $field
358
     * @param string $file
359
     *
360
     * @throws \Longman\TelegramBot\Exception\TelegramException
361
     */
362
    private static function assignEncodedFile(&$data, $field, $file)
363
    {
364
        if ($file !== null && $file !== '') {
365
            $data[$field] = self::encodeFile($file);
366
        }
367
    }
368
369
    /**
370
     * Get me
371
     *
372
     * @return mixed
373
     * @throws \Longman\TelegramBot\Exception\TelegramException
374
     */
375
    public static function getMe()
376
    {
377
        // Added fake parameter, because of some cURL version failed POST request without parameters
378
        // see https://github.com/akalongman/php-telegram-bot/pull/228
379
        return self::send('getMe', ['whoami']);
380
    }
381
382
    /**
383
     * Send message
384
     *
385
     * @param array $data
386
     *
387
     * @return mixed
388
     * @throws \Longman\TelegramBot\Exception\TelegramException
389
     */
390 5
    public static function sendMessage(array $data)
391
    {
392 5
        $text = $data['text'];
393
394
        do {
395
            //Chop off and send the first message
396 5
            $data['text'] = mb_substr($text, 0, 4096);
397 5
            $response = self::send('sendMessage', $data);
398
399
            //Prepare the next message
400 5
            $text = mb_substr($text, 4096);
401 5
        } while (mb_strlen($text, 'UTF-8') > 0);
402
403 5
        return $response;
404
    }
405
406
    /**
407
     * Forward message
408
     *
409
     * @param array $data
410
     *
411
     * @return mixed
412
     * @throws \Longman\TelegramBot\Exception\TelegramException
413
     */
414
    public static function forwardMessage(array $data)
415
    {
416
        return self::send('forwardMessage', $data);
417
    }
418
419
    /**
420
     * Send photo
421
     *
422
     * @param array  $data
423
     * @param string $file
424
     *
425
     * @return mixed
426
     * @throws \Longman\TelegramBot\Exception\TelegramException
427
     */
428
    public static function sendPhoto(array $data, $file = null)
429
    {
430
        self::assignEncodedFile($data, 'photo', $file);
431
432
        return self::send('sendPhoto', $data);
433
    }
434
435
    /**
436
     * Send audio
437
     *
438
     * @param array  $data
439
     * @param string $file
440
     *
441
     * @return mixed
442
     * @throws \Longman\TelegramBot\Exception\TelegramException
443
     */
444
    public static function sendAudio(array $data, $file = null)
445
    {
446
        self::assignEncodedFile($data, 'audio', $file);
447
448
        return self::send('sendAudio', $data);
449
    }
450
451
    /**
452
     * Send document
453
     *
454
     * @param array  $data
455
     * @param string $file
456
     *
457
     * @return mixed
458
     * @throws \Longman\TelegramBot\Exception\TelegramException
459
     */
460
    public static function sendDocument(array $data, $file = null)
461
    {
462
        self::assignEncodedFile($data, 'document', $file);
463
464
        return self::send('sendDocument', $data);
465
    }
466
467
    /**
468
     * Send sticker
469
     *
470
     * @param array  $data
471
     * @param string $file
472
     *
473
     * @return mixed
474
     * @throws \Longman\TelegramBot\Exception\TelegramException
475
     */
476
    public static function sendSticker(array $data, $file = null)
477
    {
478
        self::assignEncodedFile($data, 'sticker', $file);
479
480
        return self::send('sendSticker', $data);
481
    }
482
483
    /**
484
     * Send video
485
     *
486
     * @param array  $data
487
     * @param string $file
488
     *
489
     * @return mixed
490
     * @throws \Longman\TelegramBot\Exception\TelegramException
491
     */
492
    public static function sendVideo(array $data, $file = null)
493
    {
494
        self::assignEncodedFile($data, 'video', $file);
495
496
        return self::send('sendVideo', $data);
497
    }
498
499
    /**
500
     * Send voice
501
     *
502
     * @param array  $data
503
     * @param string $file
504
     *
505
     * @return mixed
506
     * @throws \Longman\TelegramBot\Exception\TelegramException
507
     */
508
    public static function sendVoice(array $data, $file = null)
509
    {
510
        self::assignEncodedFile($data, 'voice', $file);
511
512
        return self::send('sendVoice', $data);
513
    }
514
515
    /**
516
     * Send location
517
     *
518
     * @param array $data
519
     *
520
     * @return mixed
521
     * @throws \Longman\TelegramBot\Exception\TelegramException
522
     */
523
    public static function sendLocation(array $data)
524
    {
525
        return self::send('sendLocation', $data);
526
    }
527
528
    /**
529
     * Send venue
530
     *
531
     * @param array $data
532
     *
533
     * @return mixed
534
     * @throws \Longman\TelegramBot\Exception\TelegramException
535
     */
536
    public static function sendVenue(array $data)
537
    {
538
        return self::send('sendVenue', $data);
539
    }
540
541
    /**
542
     * Send contact
543
     *
544
     * @param array $data
545
     *
546
     * @return mixed
547
     * @throws \Longman\TelegramBot\Exception\TelegramException
548
     */
549
    public static function sendContact(array $data)
550
    {
551
        return self::send('sendContact', $data);
552
    }
553
554
    /**
555
     * Send chat action
556
     *
557
     * @param array $data
558
     *
559
     * @return mixed
560
     * @throws \Longman\TelegramBot\Exception\TelegramException
561
     */
562
    public static function sendChatAction(array $data)
563
    {
564
        return self::send('sendChatAction', $data);
565
    }
566
567
    /**
568
     * Get user profile photos
569
     *
570
     * @param array $data
571
     *
572
     * @return mixed
573
     * @throws \Longman\TelegramBot\Exception\TelegramException
574
     */
575
    public static function getUserProfilePhotos(array $data)
576
    {
577
        if (!isset($data['user_id'])) {
578
            throw new TelegramException('User id is empty!');
579
        }
580
581
        return self::send('getUserProfilePhotos', $data);
582
    }
583
584
    /**
585
     * Get updates
586
     *
587
     * @param array $data
588
     *
589
     * @return mixed
590
     * @throws \Longman\TelegramBot\Exception\TelegramException
591
     */
592
    public static function getUpdates(array $data)
593
    {
594
        return self::send('getUpdates', $data);
595
    }
596
597
    /**
598
     * Set webhook
599
     *
600
     * @param string $url
601
     * @param string $file
602
     *
603
     * @return mixed
604
     * @throws \Longman\TelegramBot\Exception\TelegramException
605
     */
606
    public static function setWebhook($url = '', $file = null)
607
    {
608
        $data = ['url' => $url];
609
610
        self::assignEncodedFile($data, 'certificate', $file);
611
612
        return self::send('setWebhook', $data);
613
    }
614
615
    /**
616
     * Get file
617
     *
618
     * @param array $data
619
     *
620
     * @return mixed
621
     * @throws \Longman\TelegramBot\Exception\TelegramException
622
     */
623
    public static function getFile(array $data)
624
    {
625
        return self::send('getFile', $data);
626
    }
627
628
    /**
629
     * Kick Chat Member
630
     *
631
     * @param array $data
632
     *
633
     * @return mixed
634
     * @throws \Longman\TelegramBot\Exception\TelegramException
635
     */
636
    public static function kickChatMember(array $data)
637
    {
638
        return self::send('kickChatMember', $data);
639
    }
640
641
    /**
642
     * Leave Chat
643
     *
644
     * @param array $data
645
     *
646
     * @return mixed
647
     * @throws \Longman\TelegramBot\Exception\TelegramException
648
     */
649
    public static function leaveChat(array $data)
650
    {
651
        return self::send('leaveChat', $data);
652
    }
653
654
    /**
655
     * Unban Chat Member
656
     *
657
     * @param array $data
658
     *
659
     * @return mixed
660
     * @throws \Longman\TelegramBot\Exception\TelegramException
661
     */
662
    public static function unbanChatMember(array $data)
663
    {
664
        return self::send('unbanChatMember', $data);
665
    }
666
667
    /**
668
     * Get Chat
669
     *
670
     * @todo add get response in ServerResponse.php?
671
     *
672
     * @param array $data
673
     *
674
     * @return mixed
675
     * @throws \Longman\TelegramBot\Exception\TelegramException
676
     */
677
    public static function getChat(array $data)
678
    {
679
        return self::send('getChat', $data);
680
    }
681
682
    /**
683
     * Get Chat Administrators
684
     *
685
     * @todo add get response in ServerResponse.php?
686
     *
687
     * @param array $data
688
     *
689
     * @return mixed
690
     * @throws \Longman\TelegramBot\Exception\TelegramException
691
     */
692
    public static function getChatAdministrators(array $data)
693
    {
694
        return self::send('getChatAdministrators', $data);
695
    }
696
697
    /**
698
     * Get Chat Members Count
699
     *
700
     * @todo add get response in ServerResponse.php?
701
     *
702
     * @param array $data
703
     *
704
     * @return mixed
705
     * @throws \Longman\TelegramBot\Exception\TelegramException
706
     */
707
    public static function getChatMembersCount(array $data)
708
    {
709
        return self::send('getChatMembersCount', $data);
710
    }
711
712
    /**
713
     * Get Chat Member
714
     *
715
     * @todo add get response in ServerResponse.php?
716
     *
717
     * @param array $data
718
     *
719
     * @return mixed
720
     * @throws \Longman\TelegramBot\Exception\TelegramException
721
     */
722
    public static function getChatMember(array $data)
723
    {
724
        return self::send('getChatMember', $data);
725
    }
726
727
    /**
728
     * Answer callback query
729
     *
730
     * @param array $data
731
     *
732
     * @return mixed
733
     * @throws \Longman\TelegramBot\Exception\TelegramException
734
     */
735
    public static function answerCallbackQuery(array $data)
736
    {
737
        return self::send('answerCallbackQuery', $data);
738
    }
739
740
    /**
741
     * Answer inline query
742
     *
743
     * @param array $data
744
     *
745
     * @return mixed
746
     * @throws \Longman\TelegramBot\Exception\TelegramException
747
     */
748
    public static function answerInlineQuery(array $data)
749
    {
750
        return self::send('answerInlineQuery', $data);
751
    }
752
753
    /**
754
     * Edit message text
755
     *
756
     * @param array $data
757
     *
758
     * @return mixed
759
     * @throws \Longman\TelegramBot\Exception\TelegramException
760
     */
761
    public static function editMessageText(array $data)
762
    {
763
        return self::send('editMessageText', $data);
764
    }
765
766
    /**
767
     * Edit message caption
768
     *
769
     * @param array $data
770
     *
771
     * @return mixed
772
     * @throws \Longman\TelegramBot\Exception\TelegramException
773
     */
774
    public static function editMessageCaption(array $data)
775
    {
776
        return self::send('editMessageCaption', $data);
777
    }
778
779
    /**
780
     * Edit message reply markup
781
     *
782
     * @param array $data
783
     *
784
     * @return mixed
785
     * @throws \Longman\TelegramBot\Exception\TelegramException
786
     */
787
    public static function editMessageReplyMarkup(array $data)
788
    {
789
        return self::send('editMessageReplyMarkup', $data);
790
    }
791
792
    /**
793
     * Return an empty Server Response
794
     *
795
     * No request to telegram are sent, this function is used in commands that
796
     * don't need to fire a message after execution
797
     *
798
     * @return \Longman\TelegramBot\Entities\ServerResponse
799
     * @throws \Longman\TelegramBot\Exception\TelegramException
800
     */
801
    public static function emptyResponse()
802
    {
803
        return new ServerResponse(['ok' => true, 'result' => true], null);
804
    }
805
806
    /**
807
     * Send message to all active chats
808
     *
809
     * @param string  $callback_function
810
     * @param array   $data
811
     * @param boolean $send_groups
812
     * @param boolean $send_super_groups
813
     * @param boolean $send_users
814
     * @param string  $date_from
815
     * @param string  $date_to
816
     *
817
     * @return array
818
     * @throws \Longman\TelegramBot\Exception\TelegramException
819
     */
820
    public static function sendToActiveChats(
821
        $callback_function,
822
        array $data,
823
        $send_groups = true,
824
        $send_super_groups = true,
825
        $send_users = true,
826
        $date_from = null,
827
        $date_to = null
828
    ) {
829
        $callback_path = __NAMESPACE__ . '\Request';
830
        if (!method_exists($callback_path, $callback_function)) {
831
            throw new TelegramException('Method "' . $callback_function . '" not found in class Request.');
832
        }
833
834
        $chats = DB::selectChats($send_groups, $send_super_groups, $send_users, $date_from, $date_to);
835
836
        $results = [];
837
        if (is_array($chats)) {
838
            foreach ($chats as $row) {
839
                $data['chat_id'] = $row['chat_id'];
840
                $results[]       = call_user_func_array($callback_path . '::' . $callback_function, [$data]);
841
            }
842
        }
843
844
        return $results;
845
    }
846
847
    /**
848
     * Use this method to get current webhook status.
849
     *
850
     * @return Entities\ServerResponse
851
     */
852
    public static function getWebhookInfo()
853
    {
854
        return self::send('getWebhookInfo', []);
855
    }
856
}
857