Completed
Branch scrutinizer_fixes (e85bf7)
by Armando
02:47
created

Request::generateGeneralFakeServerResponse()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 30
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 30
rs 8.8571
ccs 11
cts 11
cp 1
cc 3
eloc 14
nc 4
nop 1
crap 3
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
    ];
85
86
    /**
87
     * Initialize
88
     *
89
     * @param \Longman\TelegramBot\Telegram $telegram
90
     *
91
     * @throws \Longman\TelegramBot\Exception\TelegramException
92
     */
93 39
    public static function initialize(Telegram $telegram)
94
    {
95 39
        if (is_object($telegram)) {
96 39
            self::$telegram = $telegram;
97 39
            self::$client   = new Client(['base_uri' => self::$api_base_uri]);
98
        } else {
99
            throw new TelegramException('Telegram pointer is empty!');
100
        }
101 39
    }
102
103
    /**
104
     * Set input from custom input or stdin and return it
105
     *
106
     * @return string
107
     * @throws \Longman\TelegramBot\Exception\TelegramException
108
     */
109
    public static function getInput()
110
    {
111
        // First check if a custom input has been set, else get the PHP input.
112
        if (!($input = self::$telegram->getCustomInput())) {
113
            $input = file_get_contents('php://input');
114
        }
115
116
        // Make sure we have a string to work with.
117
        if (is_string($input)) {
118
            self::$input = $input;
119
        } else {
120
            throw new TelegramException('Input must be a string!');
121
        }
122
123
        TelegramLog::update(self::$input);
124
125
        return self::$input;
126
    }
127
128
    /**
129
     * Generate general fake server response
130
     *
131
     * @param array $data Data to add to fake response
132
     *
133
     * @return array Fake response data
134
     */
135 6
    public static function generateGeneralFakeServerResponse(array $data = null)
136
    {
137
        //PARAM BINDED IN PHPUNIT TEST FOR TestServerResponse.php
138
        //Maybe this is not the best possible implementation
139
140
        //No value set in $data ie testing setWebhook
141
        //Provided $data['chat_id'] ie testing sendMessage
142
143 6
        $fake_response = ['ok' => true]; // :)
144
145 6
        if ($data === null) {
146 1
            $fake_response['result'] = true;
147
        }
148
149
        //some data to let iniatilize the class method SendMessage
150 6
        if (isset($data['chat_id'])) {
151 6
            $data['message_id'] = '1234';
152 6
            $data['date']       = '1441378360';
153 6
            $data['from']       = [
154
                'id'         => 123456789,
155
                'first_name' => 'botname',
156
                'username'   => 'namebot',
157
            ];
158 6
            $data['chat']       = ['id' => $data['chat_id']];
159
160 6
            $fake_response['result'] = $data;
161
        }
162
163 6
        return $fake_response;
164
    }
165
166
    /**
167
     * Execute HTTP Request
168
     *
169
     * @param string     $action Action to execute
170
     * @param array|null $data   Data to attach to the execution
171
     *
172
     * @return mixed Result of the HTTP Request
173
     * @throws \Longman\TelegramBot\Exception\TelegramException
174
     */
175
    public static function execute($action, array $data = null)
176
    {
177
        $debug_handle = TelegramLog::getDebugLogTempStream();
178
179
        //Fix so that the keyboard markup is a string, not an object
180
        if (isset($data['reply_markup']) && !is_string($data['reply_markup'])) {
181
            $data['reply_markup'] = (string)$data['reply_markup'];
182
        }
183
184
        $request_params = ['debug' => $debug_handle];
185
186
        //Check for resources in data
187
        $contains_resource = false;
188
        foreach ($data as $item) {
189
            if (is_resource($item)) {
190
                $contains_resource = true;
191
                break;
192
            }
193
        }
194
195
        //Reformat data array in multipart way
196
        if ($contains_resource) {
197
            foreach ($data as $key => $item) {
198
                $request_params['multipart'][] = ['name' => $key, 'contents' => $item];
199
            }
200
        } else {
201
            $request_params['form_params'] = $data;
202
        }
203
204
        $result = '';
205
        try {
206
            $result = (string)self::$client->post(
207
                '/bot' . self::$telegram->getApiKey() . '/' . $action,
208
                $request_params
209
            )->getBody();
210
        } catch (RequestException $e) {
211
            throw new TelegramException($e->getMessage());
212
        } finally {
213
            //Logging verbose debug output
214
            TelegramLog::endDebugLogTempStream("Verbose HTTP Request output:\n%s\n");
215
        }
216
217
        //Logging getUpdates Update
218
        if ($action === 'getUpdates') {
219
            TelegramLog::update($result);
220
        }
221
222
        return $result;
223
    }
224
225
    /**
226
     * Download file
227
     *
228
     * @param \Longman\TelegramBot\Entities\File $file
229
     *
230
     * @return boolean
231
     * @throws \Longman\TelegramBot\Exception\TelegramException
232
     */
233
    public static function downloadFile(File $file)
234
    {
235
        $path = $file->getFilePath();
236
237
        //Create the directory
238
        $loc_path = self::$telegram->getDownloadPath() . '/' . $path;
239
240
        $dirname = dirname($loc_path);
241
        if (!is_dir($dirname) && !mkdir($dirname, 0755, true)) {
242
            throw new TelegramException('Directory ' . $dirname . ' can\'t be created');
243
        }
244
245
        $debug_handle = TelegramLog::getDebugLogTempStream();
246
247
        try {
248
            self::$client->get(
249
                '/file/bot' . self::$telegram->getApiKey() . '/' . $path,
250
                ['debug' => $debug_handle, 'sink' => $loc_path]
251
            );
252
        } catch (RequestException $e) {
253
            throw new TelegramException($e->getMessage());
254
        } finally {
255
            //Logging verbose debug output
256
            TelegramLog::endDebugLogTempStream("Verbose HTTP File Download Request output:\n%s\n");
257
        }
258
259
        return (filesize($loc_path) > 0);
260
    }
261
262
    /**
263
     * Encode file
264
     *
265
     * @param string $file
266
     *
267
     * @return resource
268
     * @throws \Longman\TelegramBot\Exception\TelegramException
269
     */
270
    protected static function encodeFile($file)
271
    {
272
        $fp = fopen($file, 'r');
273
        if ($fp === false) {
274
            throw new TelegramException('Cannot open ' . $file . ' for reading');
275
        }
276
277
        return $fp;
278
    }
279
280
    /**
281
     * Send command
282
     *
283
     * @todo Fake response doesn't need json encoding?
284
     *
285
     * @param string     $action
286
     * @param array|null $data
287
     *
288
     * @return \Longman\TelegramBot\Entities\ServerResponse
289
     * @throws \Longman\TelegramBot\Exception\TelegramException
290
     */
291 5
    public static function send($action, array $data = null)
292
    {
293 5
        self::ensureValidAction($action);
294
295 5
        $bot_name = self::$telegram->getBotName();
296
297 5
        if (defined('PHPUNIT_TESTSUITE')) {
298 5
            $fake_response = self::generateGeneralFakeServerResponse($data);
299
300 5
            return new ServerResponse($fake_response, $bot_name);
301
        }
302
303
        self::ensureNonEmptyData($data);
0 ignored issues
show
Bug introduced by
It seems like $data defined by parameter $data on line 291 can also be of type null; however, Longman\TelegramBot\Request::ensureNonEmptyData() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
304
305
        $response = json_decode(self::execute($action, $data), true);
306
307
        if (null === $response) {
308
            throw new TelegramException('Telegram returned an invalid response! Please review your bot name and API key.');
309
        }
310
311
        return new ServerResponse($response, $bot_name);
312
    }
313
314
    /**
315
     * Make sure the data isn't empty, else throw an exception
316
     *
317
     * @param array $data
318
     *
319
     * @throws \Longman\TelegramBot\Exception\TelegramException
320
     */
321
    private static function ensureNonEmptyData(array $data)
322
    {
323
        if (empty($data)) {
324
            throw new TelegramException('Data is empty!');
325
        }
326
    }
327
328
    /**
329
     * Make sure the action is valid, else throw an exception
330
     *
331
     * @param string $action
332
     *
333
     * @throws \Longman\TelegramBot\Exception\TelegramException
334
     */
335 5
    private static function ensureValidAction($action)
336
    {
337 5
        if (!in_array($action, self::$actions, true)) {
338
            throw new TelegramException('The action " . $action . " doesn\'t exist!');
339
        }
340 5
    }
341
342
    /**
343
     * Assign an encoded file to a data array
344
     *
345
     * @param array  $data
346
     * @param string $field
347
     * @param string $file
348
     *
349
     * @throws \Longman\TelegramBot\Exception\TelegramException
350
     */
351
    private static function assignEncodedFile(&$data, $field, $file)
352
    {
353
        if ($file !== null && $file !== '') {
354
            $data[$field] = self::encodeFile($file);
355
        }
356
    }
357
358
    /**
359
     * Get me
360
     *
361
     * @return mixed
362
     * @throws \Longman\TelegramBot\Exception\TelegramException
363
     */
364
    public static function getMe()
365
    {
366
        // Added fake parameter, because of some cURL version failed POST request without parameters
367
        // see https://github.com/akalongman/php-telegram-bot/pull/228
368
        return self::send('getMe', ['whoami']);
369
    }
370
371
    /**
372
     * Send message
373
     *
374
     * @todo Could do with some cleaner recursion
375
     *
376
     * @param array $data
377
     *
378
     * @return mixed
379
     * @throws \Longman\TelegramBot\Exception\TelegramException
380
     */
381 5
    public static function sendMessage(array $data)
382
    {
383 5
        $text            = $data['text'];
384 5
        $string_len_utf8 = mb_strlen($text, 'UTF-8');
385 5
        if ($string_len_utf8 > 4096) {
386
            $data['text'] = mb_substr($text, 0, 4096);
387
            self::send('sendMessage', $data);
388
            $data['text'] = mb_substr($text, 4096, $string_len_utf8);
389
390
            return self::sendMessage($data);
391
        }
392
393 5
        return self::send('sendMessage', $data);
394
    }
395
396
    /**
397
     * Forward message
398
     *
399
     * @param array $data
400
     *
401
     * @return mixed
402
     * @throws \Longman\TelegramBot\Exception\TelegramException
403
     */
404
    public static function forwardMessage(array $data)
405
    {
406
        return self::send('forwardMessage', $data);
407
    }
408
409
    /**
410
     * Send photo
411
     *
412
     * @param array  $data
413
     * @param string $file
414
     *
415
     * @return mixed
416
     * @throws \Longman\TelegramBot\Exception\TelegramException
417
     */
418
    public static function sendPhoto(array $data, $file = null)
419
    {
420
        self::assignEncodedFile($data, 'photo', $file);
421
422
        return self::send('sendPhoto', $data);
423
    }
424
425
    /**
426
     * Send audio
427
     *
428
     * @param array  $data
429
     * @param string $file
430
     *
431
     * @return mixed
432
     * @throws \Longman\TelegramBot\Exception\TelegramException
433
     */
434
    public static function sendAudio(array $data, $file = null)
435
    {
436
        self::assignEncodedFile($data, 'audio', $file);
437
438
        return self::send('sendAudio', $data);
439
    }
440
441
    /**
442
     * Send document
443
     *
444
     * @param array  $data
445
     * @param string $file
446
     *
447
     * @return mixed
448
     * @throws \Longman\TelegramBot\Exception\TelegramException
449
     */
450
    public static function sendDocument(array $data, $file = null)
451
    {
452
        self::assignEncodedFile($data, 'document', $file);
453
454
        return self::send('sendDocument', $data);
455
    }
456
457
    /**
458
     * Send sticker
459
     *
460
     * @param array  $data
461
     * @param string $file
462
     *
463
     * @return mixed
464
     * @throws \Longman\TelegramBot\Exception\TelegramException
465
     */
466
    public static function sendSticker(array $data, $file = null)
467
    {
468
        self::assignEncodedFile($data, 'sticker', $file);
469
470
        return self::send('sendSticker', $data);
471
    }
472
473
    /**
474
     * Send video
475
     *
476
     * @param array  $data
477
     * @param string $file
478
     *
479
     * @return mixed
480
     * @throws \Longman\TelegramBot\Exception\TelegramException
481
     */
482
    public static function sendVideo(array $data, $file = null)
483
    {
484
        self::assignEncodedFile($data, 'video', $file);
485
486
        return self::send('sendVideo', $data);
487
    }
488
489
    /**
490
     * Send voice
491
     *
492
     * @param array  $data
493
     * @param string $file
494
     *
495
     * @return mixed
496
     * @throws \Longman\TelegramBot\Exception\TelegramException
497
     */
498
    public static function sendVoice(array $data, $file = null)
499
    {
500
        self::assignEncodedFile($data, 'voice', $file);
501
502
        return self::send('sendVoice', $data);
503
    }
504
505
    /**
506
     * Send location
507
     *
508
     * @param array $data
509
     *
510
     * @return mixed
511
     * @throws \Longman\TelegramBot\Exception\TelegramException
512
     */
513
    public static function sendLocation(array $data)
514
    {
515
        return self::send('sendLocation', $data);
516
    }
517
518
    /**
519
     * Send venue
520
     *
521
     * @param array $data
522
     *
523
     * @return mixed
524
     * @throws \Longman\TelegramBot\Exception\TelegramException
525
     */
526
    public static function sendVenue(array $data)
527
    {
528
        return self::send('sendVenue', $data);
529
    }
530
531
    /**
532
     * Send contact
533
     *
534
     * @param array $data
535
     *
536
     * @return mixed
537
     * @throws \Longman\TelegramBot\Exception\TelegramException
538
     */
539
    public static function sendContact(array $data)
540
    {
541
        return self::send('sendContact', $data);
542
    }
543
544
    /**
545
     * Send chat action
546
     *
547
     * @param array $data
548
     *
549
     * @return mixed
550
     * @throws \Longman\TelegramBot\Exception\TelegramException
551
     */
552
    public static function sendChatAction(array $data)
553
    {
554
        return self::send('sendChatAction', $data);
555
    }
556
557
    /**
558
     * Get user profile photos
559
     *
560
     * @param array $data
561
     *
562
     * @return mixed
563
     * @throws \Longman\TelegramBot\Exception\TelegramException
564
     */
565
    public static function getUserProfilePhotos(array $data)
566
    {
567
        if (!isset($data['user_id'])) {
568
            throw new TelegramException('User id is empty!');
569
        }
570
571
        return self::send('getUserProfilePhotos', $data);
572
    }
573
574
    /**
575
     * Get updates
576
     *
577
     * @param array $data
578
     *
579
     * @return mixed
580
     * @throws \Longman\TelegramBot\Exception\TelegramException
581
     */
582
    public static function getUpdates(array $data)
583
    {
584
        return self::send('getUpdates', $data);
585
    }
586
587
    /**
588
     * Set webhook
589
     *
590
     * @param string $url
591
     * @param string $file
592
     *
593
     * @return mixed
594
     * @throws \Longman\TelegramBot\Exception\TelegramException
595
     */
596
    public static function setWebhook($url = '', $file = null)
597
    {
598
        $data = ['url' => $url];
599
600
        self::assignEncodedFile($data, 'certificate', $file);
601
602
        return self::send('setWebhook', $data);
603
    }
604
605
    /**
606
     * Get file
607
     *
608
     * @param array $data
609
     *
610
     * @return mixed
611
     * @throws \Longman\TelegramBot\Exception\TelegramException
612
     */
613
    public static function getFile(array $data)
614
    {
615
        return self::send('getFile', $data);
616
    }
617
618
    /**
619
     * Kick Chat Member
620
     *
621
     * @param array $data
622
     *
623
     * @return mixed
624
     * @throws \Longman\TelegramBot\Exception\TelegramException
625
     */
626
    public static function kickChatMember(array $data)
627
    {
628
        return self::send('kickChatMember', $data);
629
    }
630
631
    /**
632
     * Leave Chat
633
     *
634
     * @param array $data
635
     *
636
     * @return mixed
637
     * @throws \Longman\TelegramBot\Exception\TelegramException
638
     */
639
    public static function leaveChat(array $data)
640
    {
641
        return self::send('leaveChat', $data);
642
    }
643
644
    /**
645
     * Unban Chat Member
646
     *
647
     * @param array $data
648
     *
649
     * @return mixed
650
     * @throws \Longman\TelegramBot\Exception\TelegramException
651
     */
652
    public static function unbanChatMember(array $data)
653
    {
654
        return self::send('unbanChatMember', $data);
655
    }
656
657
    /**
658
     * Get Chat
659
     *
660
     * @todo add get response in ServerResponse.php?
661
     *
662
     * @param array $data
663
     *
664
     * @return mixed
665
     * @throws \Longman\TelegramBot\Exception\TelegramException
666
     */
667
    public static function getChat(array $data)
668
    {
669
        return self::send('getChat', $data);
670
    }
671
672
    /**
673
     * Get Chat Administrators
674
     *
675
     * @todo add get response in ServerResponse.php?
676
     *
677
     * @param array $data
678
     *
679
     * @return mixed
680
     * @throws \Longman\TelegramBot\Exception\TelegramException
681
     */
682
    public static function getChatAdministrators(array $data)
683
    {
684
        return self::send('getChatAdministrators', $data);
685
    }
686
687
    /**
688
     * Get Chat Members Count
689
     *
690
     * @todo add get response in ServerResponse.php?
691
     *
692
     * @param array $data
693
     *
694
     * @return mixed
695
     * @throws \Longman\TelegramBot\Exception\TelegramException
696
     */
697
    public static function getChatMembersCount(array $data)
698
    {
699
        return self::send('getChatMembersCount', $data);
700
    }
701
702
    /**
703
     * Get Chat Member
704
     *
705
     * @todo add get response in ServerResponse.php?
706
     *
707
     * @param array $data
708
     *
709
     * @return mixed
710
     * @throws \Longman\TelegramBot\Exception\TelegramException
711
     */
712
    public static function getChatMember(array $data)
713
    {
714
        return self::send('getChatMember', $data);
715
    }
716
717
    /**
718
     * Answer callback query
719
     *
720
     * @param array $data
721
     *
722
     * @return mixed
723
     * @throws \Longman\TelegramBot\Exception\TelegramException
724
     */
725
    public static function answerCallbackQuery(array $data)
726
    {
727
        return self::send('answerCallbackQuery', $data);
728
    }
729
730
    /**
731
     * Answer inline query
732
     *
733
     * @param array $data
734
     *
735
     * @return mixed
736
     * @throws \Longman\TelegramBot\Exception\TelegramException
737
     */
738
    public static function answerInlineQuery(array $data)
739
    {
740
        return self::send('answerInlineQuery', $data);
741
    }
742
743
    /**
744
     * Edit message text
745
     *
746
     * @param array $data
747
     *
748
     * @return mixed
749
     * @throws \Longman\TelegramBot\Exception\TelegramException
750
     */
751
    public static function editMessageText(array $data)
752
    {
753
        return self::send('editMessageText', $data);
754
    }
755
756
    /**
757
     * Edit message caption
758
     *
759
     * @param array $data
760
     *
761
     * @return mixed
762
     * @throws \Longman\TelegramBot\Exception\TelegramException
763
     */
764
    public static function editMessageCaption(array $data)
765
    {
766
        return self::send('editMessageCaption', $data);
767
    }
768
769
    /**
770
     * Edit message reply markup
771
     *
772
     * @param array $data
773
     *
774
     * @return mixed
775
     * @throws \Longman\TelegramBot\Exception\TelegramException
776
     */
777
    public static function editMessageReplyMarkup(array $data)
778
    {
779
        return self::send('editMessageReplyMarkup', $data);
780
    }
781
782
    /**
783
     * Return an empty Server Response
784
     *
785
     * No request to telegram are sent, this function is used in commands that
786
     * don't need to fire a message after execution
787
     *
788
     * @return \Longman\TelegramBot\Entities\ServerResponse
789
     * @throws \Longman\TelegramBot\Exception\TelegramException
790
     */
791
    public static function emptyResponse()
792
    {
793
        return new ServerResponse(['ok' => true, 'result' => true], null);
794
    }
795
796
    /**
797
     * Send message to all active chats
798
     *
799
     * @param string  $callback_function
800
     * @param array   $data
801
     * @param boolean $send_groups
802
     * @param boolean $send_super_groups
803
     * @param boolean $send_users
804
     * @param string  $date_from
805
     * @param string  $date_to
806
     *
807
     * @return array
808
     * @throws \Longman\TelegramBot\Exception\TelegramException
809
     */
810
    public static function sendToActiveChats(
811
        $callback_function,
812
        array $data,
813
        $send_groups = true,
814
        $send_super_groups = true,
815
        $send_users = true,
816
        $date_from = null,
817
        $date_to = null
818
    ) {
819
        $callback_path = __NAMESPACE__ . '\Request';
820
        if (!method_exists($callback_path, $callback_function)) {
821
            throw new TelegramException('Method "' . $callback_function . '" not found in class Request.');
822
        }
823
824
        $chats = DB::selectChats($send_groups, $send_super_groups, $send_users, $date_from, $date_to);
825
826
        $results = [];
827
        if (is_array($chats)) {
828
            foreach ($chats as $row) {
829
                $data['chat_id'] = $row['chat_id'];
830
                $results[]       = call_user_func_array($callback_path . '::' . $callback_function, [$data]);
831
            }
832
        }
833
834
        return $results;
835
    }
836
}
837