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\Commands; |
12
|
|
|
|
13
|
|
|
use Longman\TelegramBot\DB; |
14
|
|
|
use Longman\TelegramBot\Entities\CallbackQuery; |
15
|
|
|
use Longman\TelegramBot\Entities\ChosenInlineResult; |
16
|
|
|
use Longman\TelegramBot\Entities\InlineQuery; |
17
|
|
|
use Longman\TelegramBot\Entities\Message; |
18
|
|
|
use Longman\TelegramBot\Entities\Update; |
19
|
|
|
use Longman\TelegramBot\Request; |
20
|
|
|
use Longman\TelegramBot\Telegram; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Class Command |
24
|
|
|
* |
25
|
|
|
* Base class for commands. It includes some helper methods that can fetch data directly from the Update object. |
26
|
|
|
* |
27
|
|
|
* @method Message getMessage() Optional. New incoming message of any kind — text, photo, sticker, etc. |
28
|
|
|
* @method Message getEditedMessage() Optional. New version of a message that is known to the bot and was edited |
29
|
|
|
* @method Message getChannelPost() Optional. New post in the channel, can be any kind — text, photo, sticker, etc. |
30
|
|
|
* @method Message getEditedChannelPost() Optional. New version of a post in the channel that is known to the bot and was edited |
31
|
|
|
* @method InlineQuery getInlineQuery() Optional. New incoming inline query |
32
|
|
|
* @method ChosenInlineResult getChosenInlineResult() Optional. The result of an inline query that was chosen by a user and sent to their chat partner. |
33
|
|
|
* @method CallbackQuery getCallbackQuery() Optional. New incoming callback query |
34
|
|
|
*/ |
35
|
|
|
abstract class Command |
36
|
|
|
{ |
37
|
|
|
/** |
38
|
|
|
* Telegram object |
39
|
|
|
* |
40
|
|
|
* @var \Longman\TelegramBot\Telegram |
41
|
|
|
*/ |
42
|
|
|
protected $telegram; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Update object |
46
|
|
|
* |
47
|
|
|
* @var \Longman\TelegramBot\Entities\Update |
48
|
|
|
*/ |
49
|
|
|
protected $update; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Name |
53
|
|
|
* |
54
|
|
|
* @var string |
55
|
|
|
*/ |
56
|
|
|
protected $name = ''; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Description |
60
|
|
|
* |
61
|
|
|
* @var string |
62
|
|
|
*/ |
63
|
|
|
protected $description = 'Command description'; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Usage |
67
|
|
|
* |
68
|
|
|
* @var string |
69
|
|
|
*/ |
70
|
|
|
protected $usage = 'Command usage'; |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Show in Help |
74
|
|
|
* |
75
|
|
|
* @var bool |
76
|
|
|
*/ |
77
|
|
|
protected $show_in_help = true; |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Version |
81
|
|
|
* |
82
|
|
|
* @var string |
83
|
|
|
*/ |
84
|
|
|
protected $version = '1.0.0'; |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* If this command is enabled |
88
|
|
|
* |
89
|
|
|
* @var boolean |
90
|
|
|
*/ |
91
|
|
|
protected $enabled = true; |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* If this command needs mysql |
95
|
|
|
* |
96
|
|
|
* @var boolean |
97
|
|
|
*/ |
98
|
|
|
protected $need_mysql = false; |
99
|
|
|
|
100
|
|
|
/* |
101
|
|
|
* Make sure this command only executes on a private chat. |
102
|
|
|
* |
103
|
|
|
* @var bool |
104
|
|
|
*/ |
105
|
|
|
protected $private_only = false; |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Command config |
109
|
|
|
* |
110
|
|
|
* @var array |
111
|
|
|
*/ |
112
|
|
|
protected $config = []; |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* Constructor |
116
|
|
|
* |
117
|
|
|
* @param \Longman\TelegramBot\Telegram $telegram |
118
|
|
|
* @param \Longman\TelegramBot\Entities\Update $update |
119
|
|
|
*/ |
120
|
15 |
|
public function __construct(Telegram $telegram, Update $update = null) |
121
|
|
|
{ |
122
|
15 |
|
$this->telegram = $telegram; |
123
|
15 |
|
$this->setUpdate($update); |
124
|
15 |
|
$this->config = $telegram->getCommandConfig($this->name); |
125
|
15 |
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Set update object |
129
|
|
|
* |
130
|
|
|
* @param \Longman\TelegramBot\Entities\Update $update |
131
|
|
|
* |
132
|
|
|
* @return \Longman\TelegramBot\Commands\Command |
133
|
|
|
*/ |
134
|
15 |
|
public function setUpdate(Update $update = null) |
135
|
|
|
{ |
136
|
15 |
|
if ($update !== null) { |
137
|
1 |
|
$this->update = $update; |
138
|
|
|
} |
139
|
|
|
|
140
|
15 |
|
return $this; |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* Pre-execute command |
145
|
|
|
* |
146
|
|
|
* @return \Longman\TelegramBot\Entities\ServerResponse |
147
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
148
|
|
|
*/ |
149
|
|
|
public function preExecute() |
150
|
|
|
{ |
151
|
|
|
if ($this->need_mysql && !($this->telegram->isDbEnabled() && DB::isDbConnected())) { |
152
|
|
|
return $this->executeNoDb(); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
if ($this->isPrivateOnly() && $this->removeNonPrivateMessage()) { |
156
|
|
|
$message = $this->getMessage(); |
157
|
|
|
|
158
|
|
|
if ($user = $message->getFrom()) { |
159
|
|
|
return Request::sendMessage([ |
160
|
|
|
'chat_id' => $user->getId(), |
161
|
|
|
'parse_mode' => 'Markdown', |
162
|
|
|
'text' => sprintf( |
163
|
|
|
"/%s command is only available in a private chat.\n(`%s`)", |
164
|
|
|
$this->getName(), |
165
|
|
|
$message->getText() |
166
|
|
|
), |
167
|
|
|
]); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
return Request::emptyResponse(); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
return $this->execute(); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* Execute command |
178
|
|
|
* |
179
|
|
|
* @return \Longman\TelegramBot\Entities\ServerResponse |
180
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
181
|
|
|
*/ |
182
|
|
|
abstract public function execute(); |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Execution if MySQL is required but not available |
186
|
|
|
* |
187
|
|
|
* @return \Longman\TelegramBot\Entities\ServerResponse |
188
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
189
|
|
|
*/ |
190
|
|
View Code Duplication |
public function executeNoDb() |
|
|
|
|
191
|
|
|
{ |
192
|
|
|
//Preparing message |
193
|
|
|
$message = $this->getMessage(); |
194
|
|
|
$chat_id = $message->getChat()->getId(); |
195
|
|
|
|
196
|
|
|
$data = [ |
197
|
|
|
'chat_id' => $chat_id, |
198
|
|
|
'text' => 'Sorry no database connection, unable to execute "' . $this->name . '" command.', |
199
|
|
|
]; |
200
|
|
|
|
201
|
|
|
return Request::sendMessage($data); |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Get update object |
206
|
|
|
* |
207
|
|
|
* @return \Longman\TelegramBot\Entities\Update |
208
|
|
|
*/ |
209
|
1 |
|
public function getUpdate() |
210
|
|
|
{ |
211
|
1 |
|
return $this->update; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* Relay any non-existing function calls to Update object. |
216
|
|
|
* |
217
|
|
|
* This is purely a helper method to make requests from within execute() method easier. |
218
|
|
|
* |
219
|
|
|
* @param string $name |
220
|
|
|
* @param array $arguments |
221
|
|
|
* |
222
|
|
|
* @return Command |
223
|
|
|
*/ |
224
|
1 |
|
public function __call($name, array $arguments) |
225
|
|
|
{ |
226
|
1 |
|
if ($this->update === null) { |
227
|
1 |
|
return null; |
228
|
|
|
} |
229
|
1 |
|
return call_user_func_array([$this->update, $name], $arguments); |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* Get command config |
234
|
|
|
* |
235
|
|
|
* Look for config $name if found return it, if not return null. |
236
|
|
|
* If $name is not set return all set config. |
237
|
|
|
* |
238
|
|
|
* @param string|null $name |
239
|
|
|
* |
240
|
|
|
* @return array|mixed|null |
241
|
|
|
*/ |
242
|
1 |
|
public function getConfig($name = null) |
243
|
|
|
{ |
244
|
1 |
|
if ($name === null) { |
245
|
1 |
|
return $this->config; |
246
|
|
|
} |
247
|
1 |
|
if (isset($this->config[$name])) { |
248
|
1 |
|
return $this->config[$name]; |
249
|
|
|
} |
250
|
|
|
|
251
|
1 |
|
return null; |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
/** |
255
|
|
|
* Get telegram object |
256
|
|
|
* |
257
|
|
|
* @return \Longman\TelegramBot\Telegram |
258
|
|
|
*/ |
259
|
1 |
|
public function getTelegram() |
260
|
|
|
{ |
261
|
1 |
|
return $this->telegram; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
/** |
265
|
|
|
* Get usage |
266
|
|
|
* |
267
|
|
|
* @return string |
268
|
|
|
*/ |
269
|
1 |
|
public function getUsage() |
270
|
|
|
{ |
271
|
1 |
|
return $this->usage; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* Get version |
276
|
|
|
* |
277
|
|
|
* @return string |
278
|
|
|
*/ |
279
|
1 |
|
public function getVersion() |
280
|
|
|
{ |
281
|
1 |
|
return $this->version; |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
/** |
285
|
|
|
* Get description |
286
|
|
|
* |
287
|
|
|
* @return string |
288
|
|
|
*/ |
289
|
1 |
|
public function getDescription() |
290
|
|
|
{ |
291
|
1 |
|
return $this->description; |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
/** |
295
|
|
|
* Get name |
296
|
|
|
* |
297
|
|
|
* @return string |
298
|
|
|
*/ |
299
|
1 |
|
public function getName() |
300
|
|
|
{ |
301
|
1 |
|
return $this->name; |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
/** |
305
|
|
|
* Get Show in Help |
306
|
|
|
* |
307
|
|
|
* @return bool |
308
|
|
|
*/ |
309
|
1 |
|
public function showInHelp() |
310
|
|
|
{ |
311
|
1 |
|
return $this->show_in_help; |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* Check if command is enabled |
316
|
|
|
* |
317
|
|
|
* @return bool |
318
|
|
|
*/ |
319
|
1 |
|
public function isEnabled() |
320
|
|
|
{ |
321
|
1 |
|
return $this->enabled; |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* If this command is intended for private chats only. |
326
|
|
|
* |
327
|
|
|
* @return bool |
328
|
|
|
*/ |
329
|
|
|
public function isPrivateOnly() |
330
|
|
|
{ |
331
|
|
|
return $this->private_only; |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* If this is a SystemCommand |
336
|
|
|
* |
337
|
|
|
* @return bool |
338
|
|
|
*/ |
339
|
|
|
public function isSystemCommand() |
340
|
|
|
{ |
341
|
|
|
return ($this instanceof SystemCommand); |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* If this is an AdminCommand |
346
|
|
|
* |
347
|
|
|
* @return bool |
348
|
|
|
*/ |
349
|
|
|
public function isAdminCommand() |
350
|
|
|
{ |
351
|
|
|
return ($this instanceof AdminCommand); |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
/** |
355
|
|
|
* If this is a UserCommand |
356
|
|
|
* |
357
|
|
|
* @return bool |
358
|
|
|
*/ |
359
|
|
|
public function isUserCommand() |
360
|
|
|
{ |
361
|
|
|
return ($this instanceof UserCommand); |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
/** |
365
|
|
|
* Delete the current message if it has been called in a non-private chat. |
366
|
|
|
* |
367
|
|
|
* @return bool |
368
|
|
|
*/ |
369
|
|
|
protected function removeNonPrivateMessage() |
370
|
|
|
{ |
371
|
|
|
$message = $this->getMessage() ?: $this->getEditedMessage(); |
372
|
|
|
|
373
|
|
|
if ($message) { |
374
|
|
|
$chat = $message->getChat(); |
375
|
|
|
|
376
|
|
|
if (!$chat->isPrivateChat()) { |
377
|
|
|
// Delete the falsely called command message. |
378
|
|
|
Request::deleteMessage([ |
379
|
|
|
'chat_id' => $chat->getId(), |
380
|
|
|
'message_id' => $message->getMessageId(), |
381
|
|
|
]); |
382
|
|
|
|
383
|
|
|
return true; |
384
|
|
|
} |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
return false; |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
/** |
391
|
|
|
* Helper to reply to a chat directly. |
392
|
|
|
* |
393
|
|
|
* @param string $text |
394
|
|
|
* @param array $data |
395
|
|
|
* |
396
|
|
|
* @return \Longman\TelegramBot\Entities\ServerResponse |
397
|
|
|
*/ |
398
|
|
|
public function replyToChat($text, array $data = []) |
399
|
|
|
{ |
400
|
|
|
if ($message = $this->getMessage() ?: $this->getEditedMessage() ?: $this->getChannelPost() ?: $this->getEditedChannelPost()) { |
401
|
|
|
return Request::sendMessage(array_merge([ |
402
|
|
|
'chat_id' => $message->getChat()->getId(), |
403
|
|
|
'text' => $text, |
404
|
|
|
], $data)); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
return Request::emptyResponse(); |
408
|
|
|
} |
409
|
|
|
|
410
|
|
|
/** |
411
|
|
|
* Helper to reply to a user directly. |
412
|
|
|
* |
413
|
|
|
* @param string $text |
414
|
|
|
* @param array $data |
415
|
|
|
* |
416
|
|
|
* @return \Longman\TelegramBot\Entities\ServerResponse |
417
|
|
|
*/ |
418
|
|
|
public function replyToUser($text, array $data = []) |
419
|
|
|
{ |
420
|
|
|
if ($message = $this->getMessage() ?: $this->getEditedMessage()) { |
421
|
|
|
return Request::sendMessage(array_merge([ |
422
|
|
|
'chat_id' => $message->getFrom()->getId(), |
423
|
|
|
'text' => $text, |
424
|
|
|
], $data)); |
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
return Request::emptyResponse(); |
428
|
|
|
} |
429
|
|
|
} |
430
|
|
|
|
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.