Completed
Push — master ( 310cb4...18aaff )
by Gusev
02:59
created

Client::inlineQuery()   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 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
namespace TelegramBot\Api;
4
5
use Closure;
6
use ReflectionFunction;
7
use TelegramBot\Api\Events\EventCollection;
8
use TelegramBot\Api\Types\Message;
9
use TelegramBot\Api\Types\Update;
10
11
/**
12
 * Class Client
13
 *
14
 * @package TelegramBot\Api
15
 */
16
class Client
17
{
18
    /**
19
     * RegExp for bot commands
20
     */
21
    const REGEXP = '/^\/([^\s@]+)(@\S+)?\s?(.*)$/';
22
23
    /**
24
     * @var \TelegramBot\Api\BotApi
25
     */
26
    protected $api;
27
28
    /**
29
     * @var \TelegramBot\Api\Events\EventCollection
30
     */
31
    protected $events;
32
33
    /**
34
     * Client constructor
35
     *
36
     * @param string $token Telegram Bot API token
37
     * @param string|null $trackerToken Yandex AppMetrica application api_key
38
     */
39
    public function __construct($token, $trackerToken = null)
40
    {
41
        $this->api = new BotApi($token);
42
        $this->events = new EventCollection($trackerToken);
43
    }
44
45
    /**
46
     * Use this method to add command. Parameters will be automatically parsed and passed to closure.
47
     *
48
     * @param string $name
49
     * @param \Closure $action
50
     *
51
     * @return \TelegramBot\Api\Client
52
     */
53
    public function command($name, Closure $action)
54
    {
55
        return $this->on(self::getEvent($action), self::getChecker($name));
56
    }
57
58
    public function inlineQuery(Closure $action)
59
    {
60
        return $this->on(self::getInlineQueryEvent($action), self::getInlineQueryChecker());
61
    }
62
63
    /**
64
     * Use this method to add an event.
65
     * If second closure will return true (or if you are passed null instead of closure), first one will be executed.
66
     *
67
     * @param \Closure $event
68
     * @param \Closure|null $checker
69
     *
70
     * @return \TelegramBot\Api\Client
71
     */
72
    public function on(Closure $event, Closure $checker = null)
73
    {
74
        $this->events->add($event, $checker);
75
76
        return $this;
77
    }
78
79
    /**
80
     * Handle updates
81
     *
82
     * @param Update[] $updates
83
     */
84
    public function handle(array $updates)
85
    {
86
        foreach ($updates as $update) {
87
            /* @var \TelegramBot\Api\Types\Update $update */
88
            $this->events->handle($update);
89
        }
90
    }
91
92
    /**
93
     * Webhook handler
94
     *
95
     * @return array
96
     * @throws \TelegramBot\Api\InvalidJsonException
97
     */
98
    public function run()
99
    {
100
        if ($data = BotApi::jsonValidate(file_get_contents('php://input'), true)) {
101
            $this->handle([Update::fromResponse($data)]);
102
        }
103
    }
104
105
    /**
106
     * Returns event function to handling the command.
107
     *
108
     * @param \Closure $action
109
     *
110
     * @return \Closure
111
     */
112
    protected static function getEvent(Closure $action)
113
    {
114
        return function (Update $update) use ($action) {
115
            $message = $update->getMessage();
116
            preg_match(self::REGEXP, $message->getText(), $matches);
117
118
            if (isset($matches[3]) && !empty($matches[3])) {
119
                $parameters = str_getcsv($matches[3], chr(32));
120
            } else {
121
                $parameters = [];
122
            }
123
124
            array_unshift($parameters, $message);
125
126
            $action = new ReflectionFunction($action);
127
128
            if (count($parameters) >= $action->getNumberOfRequiredParameters()) {
129
                $action->invokeArgs($parameters);
130
            }
131
132
            return false;
133
        };
134
    }
135
136
    protected static function getInlineQueryEvent(Closure $action)
137
    {
138
        return function (Update $update) use ($action) {
139
            $action = new ReflectionFunction($action);
140
            $action->invokeArgs([$update->getInlineQuery()]);
141
142
            return false;
143
        };
144
    }
145
146
    /**
147
     * Returns check function to handling the command.
148
     *
149
     * @param string $name
150
     *
151
     * @return \Closure
152
     */
153
    protected static function getChecker($name)
154
    {
155
        return function (Update $update) use ($name) {
156
            $message = $update->getMessage();
157
            if (!strlen($message->getText())) {
158
                return false;
159
            }
160
161
            preg_match(self::REGEXP, $message->getText(), $matches);
162
163
            return !empty($matches) && $matches[1] == $name;
164
        };
165
    }
166
167
    /**
168
     * Returns check function to handling the inline queries.
169
     *
170
     * @return Closure
171
     */
172
    protected static function getInlineQueryChecker()
173
    {
174
        return function (Update $update) {
175
            return !is_null($update->getInlineQuery());
176
        };
177
    }
178
179
180
    public function __call($name, array $arguments)
181
    {
182
        if (method_exists($this, $name)) {
183
            return call_user_func_array([$this, $name], $arguments);
184
        } elseif (method_exists($this->api, $name)) {
185
            return call_user_func_array([$this->api, $name], $arguments);
186
        }
187
        throw new BadMethodCallException("Method {$name} not exists");
188
    }
189
}
190