1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Telegram\Bot\Commands; |
4
|
|
|
|
5
|
|
|
use Telegram\Bot\Answers\AnswerBus; |
6
|
|
|
use Telegram\Bot\Api; |
7
|
|
|
use Telegram\Bot\Objects\Update; |
8
|
|
|
use Telegram\Bot\Exceptions\TelegramSDKException; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Class CommandBus. |
12
|
|
|
*/ |
13
|
|
|
class CommandBus extends AnswerBus |
14
|
|
|
{ |
15
|
|
|
/** |
16
|
|
|
* @var Command[] Holds all commands. |
17
|
|
|
*/ |
18
|
|
|
protected $commands = []; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* @var Command[] Holds all commands' aliases. |
22
|
|
|
*/ |
23
|
|
|
protected $commandAliases = []; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Instantiate Command Bus. |
27
|
|
|
* |
28
|
|
|
* @param Api $telegram |
29
|
|
|
* |
30
|
|
|
* @throws TelegramSDKException |
31
|
|
|
*/ |
32
|
92 |
|
public function __construct(Api $telegram) |
33
|
|
|
{ |
34
|
92 |
|
$this->telegram = $telegram; |
35
|
92 |
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Returns the list of commands. |
39
|
|
|
* |
40
|
|
|
* @return array |
41
|
|
|
*/ |
42
|
10 |
|
public function getCommands() |
43
|
|
|
{ |
44
|
10 |
|
return $this->commands; |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Add a list of commands. |
49
|
|
|
* |
50
|
|
|
* @param array $commands |
51
|
|
|
* |
52
|
|
|
* @return CommandBus |
53
|
|
|
*/ |
54
|
8 |
|
public function addCommands(array $commands) |
55
|
|
|
{ |
56
|
8 |
|
foreach ($commands as $command) { |
57
|
8 |
|
$this->addCommand($command); |
58
|
8 |
|
} |
59
|
|
|
|
60
|
8 |
|
return $this; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Add a command to the commands list. |
65
|
|
|
* |
66
|
|
|
* @param CommandInterface|string $command Either an object or full path to the command class. |
67
|
|
|
* |
68
|
|
|
* @throws TelegramSDKException |
69
|
|
|
* |
70
|
|
|
* @return CommandBus |
71
|
|
|
*/ |
72
|
20 |
|
public function addCommand($command) |
73
|
|
|
{ |
74
|
20 |
|
$command = $this->resolveCommandObject($command); |
75
|
12 |
|
|
76
|
2 |
|
/* |
77
|
2 |
|
* At this stage we definitely have a proper command to use. |
78
|
2 |
|
* |
79
|
|
|
* @var Command $command |
80
|
2 |
|
*/ |
81
|
2 |
|
$this->commands[$command->getName()] = $command; |
82
|
|
|
|
83
|
|
|
$aliases = $command->getAliases(); |
84
|
10 |
|
|
85
|
2 |
|
if (empty($aliases)) { |
86
|
2 |
|
return $this; |
87
|
8 |
|
} |
88
|
|
|
|
89
|
10 |
|
foreach ($command->getAliases() as $alias) { |
90
|
|
View Code Duplication |
if (isset($this->commands[$alias])) { |
|
|
|
|
91
|
18 |
|
throw new TelegramSDKException(sprintf( |
92
|
|
|
'[Error] Alias [%s] conflicts with command name of "%s" try with another name or remove this alias from the list.', |
93
|
|
|
$alias, |
94
|
|
|
get_class($command) |
95
|
|
|
)); |
96
|
|
|
} |
97
|
|
|
|
98
|
16 |
View Code Duplication |
if (isset($this->commandAliases[$alias])) { |
|
|
|
|
99
|
|
|
throw new TelegramSDKException(sprintf( |
100
|
16 |
|
'[Error] Alias [%s] conflicts with another command\'s alias list: "%s", try with another name or remove this alias from the list.', |
101
|
|
|
$alias, |
102
|
16 |
|
get_class($command) |
103
|
16 |
|
)); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
$this->commandAliases[$alias] = $command; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
return $this; |
110
|
|
|
|
111
|
|
|
|
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* Remove a command from the list. |
116
|
|
|
* |
117
|
|
|
* @param $name |
118
|
|
|
* |
119
|
|
|
* @return CommandBus |
120
|
|
|
*/ |
121
|
|
|
public function removeCommand($name) |
122
|
|
|
{ |
123
|
|
|
unset($this->commands[$name]); |
124
|
|
|
|
125
|
|
|
return $this; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
2 |
|
* Removes a list of commands. |
130
|
2 |
|
* |
131
|
2 |
|
* @param array $names |
132
|
2 |
|
* |
133
|
2 |
|
* @return CommandBus |
134
|
2 |
|
*/ |
135
|
|
|
public function removeCommands(array $names) |
136
|
|
|
{ |
137
|
|
|
foreach ($names as $name) { |
138
|
|
|
$this->removeCommand($name); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
return $this; |
142
|
|
|
} |
143
|
|
|
|
144
|
4 |
|
/** |
145
|
|
|
* Parse a Command for a Match. |
146
|
4 |
|
* |
147
|
|
|
* @param $text |
148
|
4 |
|
* |
149
|
|
|
* @throws \InvalidArgumentException |
150
|
|
|
* |
151
|
|
|
* @return array |
152
|
|
|
*/ |
153
|
|
|
public function parseCommand($text) |
154
|
|
|
{ |
155
|
|
|
if (trim($text) === '') { |
156
|
|
|
throw new \InvalidArgumentException('Message is empty, Cannot parse for command'); |
157
|
|
|
} |
158
|
2 |
|
|
159
|
|
|
preg_match('/^\/([^\s@]+)@?(\S+)?\s?(.*)$/s', $text, $matches); |
160
|
2 |
|
|
161
|
2 |
|
return $matches; |
162
|
2 |
|
} |
163
|
|
|
|
164
|
2 |
|
/** |
165
|
|
|
* Handles Inbound Messages and Executes Appropriate Command. |
166
|
|
|
* |
167
|
|
|
* @param $message |
168
|
|
|
* @param $update |
169
|
|
|
* |
170
|
|
|
* @throws TelegramSDKException |
171
|
|
|
* |
172
|
|
|
* @return Update |
173
|
|
|
*/ |
174
|
|
|
protected function handler($message, Update $update) |
175
|
|
|
{ |
176
|
16 |
|
$match = $this->parseCommand($message); |
177
|
|
|
if (!empty($match)) { |
178
|
16 |
|
$command = strtolower($match[1]); //All commands must be lowercase. |
179
|
2 |
|
// $bot = (!empty($match[2])) ? $match[2] : ''; |
180
|
|
|
$arguments = $match[3]; |
181
|
|
|
|
182
|
14 |
|
$this->execute($command, $arguments, $update); |
183
|
|
|
} |
184
|
14 |
|
|
185
|
|
|
return $update; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
/** |
189
|
|
|
* Execute the command. |
190
|
|
|
* |
191
|
|
|
* @param $name |
192
|
|
|
* @param $arguments |
193
|
|
|
* @param $message |
194
|
|
|
* |
195
|
|
|
* @return mixed |
196
|
|
|
*/ |
197
|
8 |
|
protected function execute($name, $arguments, $message) |
198
|
|
|
{ |
199
|
8 |
|
if (array_key_exists($name, $this->commands)) { |
200
|
8 |
|
return $this->commands[$name]->make($this->telegram, $arguments, $message); |
201
|
8 |
View Code Duplication |
} elseif (array_key_exists($name, $this->commandAliases)) { |
|
|
|
|
202
|
|
|
return $this->commandAliases[$name]->make($this->telegram, $arguments, $message); |
203
|
8 |
|
} elseif ($command = collect($this->commands)->filter(function($command) use ($name){ |
204
|
|
|
return $command instanceof $name; |
205
|
8 |
|
})->first()) { |
206
|
8 |
|
$command->make($this->telegram, $arguments, $message); |
207
|
|
View Code Duplication |
} elseif (array_key_exists('help', $this->commands)) { |
|
|
|
|
208
|
8 |
|
return $this->commands['help']->make($this->telegram, $arguments, $message); |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
return 'Ok'; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* @param $command |
216
|
|
|
* @return object |
217
|
|
|
* @throws \Telegram\Bot\Exceptions\TelegramSDKException |
218
|
|
|
*/ |
219
|
|
|
private function resolveCommandObject($command) |
220
|
10 |
|
{ |
221
|
|
|
if (! is_object($command)) { |
222
|
10 |
|
if (! class_exists($command)) { |
223
|
6 |
|
throw new TelegramSDKException(sprintf('Command class "%s" not found! Please make sure the class exists.', $command)); |
224
|
4 |
|
} |
225
|
|
|
|
226
|
4 |
|
if ($this->telegram->hasContainer()) { |
227
|
|
|
$command = $this->buildDependencyInjectedAnswer($command); |
228
|
|
|
} else { |
229
|
|
|
$command = new $command(); |
230
|
4 |
|
} |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
if (!($command instanceof CommandInterface)) { |
234
|
|
|
|
235
|
|
|
throw new TelegramSDKException( |
236
|
|
|
sprintf( |
237
|
|
|
'Command class "%s" should be an instance of "Telegram\Bot\Commands\CommandInterface"', |
238
|
|
|
get_class($command) |
239
|
|
|
) |
240
|
|
|
); |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
return $command; |
244
|
|
|
} |
245
|
|
|
} |
246
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.