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