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
|
1 |
|
define('BASE_PATH', __DIR__); |
14
|
1 |
|
define('BASE_COMMANDS_PATH', BASE_PATH . '/Commands'); |
15
|
|
|
|
16
|
|
|
use Exception; |
17
|
|
|
use Longman\TelegramBot\Commands\Command; |
18
|
|
|
use Longman\TelegramBot\Entities\ServerResponse; |
19
|
|
|
use Longman\TelegramBot\Entities\Update; |
20
|
|
|
use Longman\TelegramBot\Exception\TelegramException; |
21
|
|
|
use PDO; |
22
|
|
|
use RecursiveDirectoryIterator; |
23
|
|
|
use RecursiveIteratorIterator; |
24
|
|
|
use RegexIterator; |
25
|
|
|
|
26
|
|
|
class Telegram |
27
|
|
|
{ |
28
|
|
|
/** |
29
|
|
|
* Version |
30
|
|
|
* |
31
|
|
|
* @var string |
32
|
|
|
*/ |
33
|
|
|
protected $version = '0.45.0'; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Telegram API key |
37
|
|
|
* |
38
|
|
|
* @var string |
39
|
|
|
*/ |
40
|
|
|
protected $api_key = ''; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Telegram Bot username |
44
|
|
|
* |
45
|
|
|
* @var string |
46
|
|
|
*/ |
47
|
|
|
protected $bot_username = ''; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Telegram Bot id |
51
|
|
|
* |
52
|
|
|
* @var string |
53
|
|
|
*/ |
54
|
|
|
protected $bot_id = ''; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Raw request data (json) for webhook methods |
58
|
|
|
* |
59
|
|
|
* @var string |
60
|
|
|
*/ |
61
|
|
|
protected $input; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Custom commands paths |
65
|
|
|
* |
66
|
|
|
* @var array |
67
|
|
|
*/ |
68
|
|
|
protected $commands_paths = []; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Current Update object |
72
|
|
|
* |
73
|
|
|
* @var \Longman\TelegramBot\Entities\Update |
74
|
|
|
*/ |
75
|
|
|
protected $update; |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Upload path |
79
|
|
|
* |
80
|
|
|
* @var string |
81
|
|
|
*/ |
82
|
|
|
protected $upload_path; |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* Download path |
86
|
|
|
* |
87
|
|
|
* @var string |
88
|
|
|
*/ |
89
|
|
|
protected $download_path; |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* MySQL integration |
93
|
|
|
* |
94
|
|
|
* @var boolean |
95
|
|
|
*/ |
96
|
|
|
protected $mysql_enabled = false; |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* PDO object |
100
|
|
|
* |
101
|
|
|
* @var \PDO |
102
|
|
|
*/ |
103
|
|
|
protected $pdo; |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* Commands config |
107
|
|
|
* |
108
|
|
|
* @var array |
109
|
|
|
*/ |
110
|
|
|
protected $commands_config = []; |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Admins list |
114
|
|
|
* |
115
|
|
|
* @var array |
116
|
|
|
*/ |
117
|
|
|
protected $admins_list = []; |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* ServerResponse of the last Command execution |
121
|
|
|
* |
122
|
|
|
* @var \Longman\TelegramBot\Entities\ServerResponse |
123
|
|
|
*/ |
124
|
|
|
protected $last_command_response; |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Botan.io integration |
128
|
|
|
* |
129
|
|
|
* @var boolean |
130
|
|
|
*/ |
131
|
|
|
protected $botan_enabled = false; |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* Check if runCommands() is running in this session |
135
|
|
|
* |
136
|
|
|
* @var boolean |
137
|
|
|
*/ |
138
|
|
|
protected $run_commands = false; |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Telegram constructor. |
142
|
|
|
* |
143
|
|
|
* @param string $api_key |
144
|
|
|
* @param string $bot_username |
145
|
|
|
* |
146
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
147
|
|
|
*/ |
148
|
30 |
|
public function __construct($api_key, $bot_username = '') |
149
|
|
|
{ |
150
|
30 |
|
if (empty($api_key)) { |
151
|
1 |
|
throw new TelegramException('API KEY not defined!'); |
152
|
|
|
} |
153
|
30 |
|
preg_match('/(\d+)\:[\w\-]+/', $api_key, $matches); |
154
|
30 |
|
if (!isset($matches[1])) { |
155
|
1 |
|
throw new TelegramException('Invalid API KEY defined!'); |
156
|
|
|
} |
157
|
30 |
|
$this->bot_id = $matches[1]; |
158
|
30 |
|
$this->api_key = $api_key; |
159
|
|
|
|
160
|
30 |
|
if (!empty($bot_username)) { |
161
|
30 |
|
$this->bot_username = $bot_username; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
//Add default system commands path |
165
|
30 |
|
$this->addCommandsPath(BASE_COMMANDS_PATH . '/SystemCommands'); |
166
|
|
|
|
167
|
30 |
|
Request::initialize($this); |
168
|
30 |
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* Initialize Database connection |
172
|
|
|
* |
173
|
|
|
* @param array $credential |
174
|
|
|
* @param string $table_prefix |
175
|
|
|
* @param string $encoding |
176
|
|
|
* |
177
|
|
|
* @return \Longman\TelegramBot\Telegram |
178
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
179
|
|
|
*/ |
180
|
9 |
View Code Duplication |
public function enableMySql(array $credential, $table_prefix = null, $encoding = 'utf8mb4') |
|
|
|
|
181
|
|
|
{ |
182
|
9 |
|
$this->pdo = DB::initialize($credential, $this, $table_prefix, $encoding); |
183
|
9 |
|
ConversationDB::initializeConversation(); |
184
|
9 |
|
$this->mysql_enabled = true; |
185
|
|
|
|
186
|
9 |
|
return $this; |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Initialize Database external connection |
191
|
|
|
* |
192
|
|
|
* @param PDO $external_pdo_connection PDO database object |
193
|
|
|
* @param string $table_prefix |
194
|
|
|
* |
195
|
|
|
* @return \Longman\TelegramBot\Telegram |
196
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
197
|
|
|
*/ |
198
|
|
View Code Duplication |
public function enableExternalMySql($external_pdo_connection, $table_prefix = null) |
|
|
|
|
199
|
|
|
{ |
200
|
|
|
$this->pdo = DB::externalInitialize($external_pdo_connection, $this, $table_prefix); |
201
|
|
|
ConversationDB::initializeConversation(); |
202
|
|
|
$this->mysql_enabled = true; |
203
|
|
|
|
204
|
|
|
return $this; |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* Get commands list |
209
|
|
|
* |
210
|
|
|
* @return array $commands |
211
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
212
|
|
|
*/ |
213
|
1 |
|
public function getCommandsList() |
214
|
|
|
{ |
215
|
1 |
|
$commands = []; |
216
|
|
|
|
217
|
1 |
|
foreach ($this->commands_paths as $path) { |
218
|
|
|
try { |
219
|
|
|
//Get all "*Command.php" files |
220
|
1 |
|
$files = new RegexIterator( |
221
|
1 |
|
new RecursiveIteratorIterator( |
222
|
1 |
|
new RecursiveDirectoryIterator($path) |
223
|
|
|
), |
224
|
1 |
|
'/^.+Command.php$/' |
225
|
|
|
); |
226
|
|
|
|
227
|
1 |
|
foreach ($files as $file) { |
228
|
|
|
//Remove "Command.php" from filename |
229
|
1 |
|
$command = $this->sanitizeCommand(substr($file->getFilename(), 0, -11)); |
230
|
1 |
|
$command_name = strtolower($command); |
231
|
|
|
|
232
|
1 |
|
if (array_key_exists($command_name, $commands)) { |
233
|
|
|
continue; |
234
|
|
|
} |
235
|
|
|
|
236
|
1 |
|
require_once $file->getPathname(); |
237
|
|
|
|
238
|
1 |
|
$command_obj = $this->getCommandObject($command); |
239
|
1 |
|
if ($command_obj instanceof Command) { |
240
|
1 |
|
$commands[$command_name] = $command_obj; |
241
|
|
|
} |
242
|
|
|
} |
243
|
|
|
} catch (Exception $e) { |
244
|
|
|
throw new TelegramException('Error getting commands from path: ' . $path); |
245
|
|
|
} |
246
|
|
|
} |
247
|
|
|
|
248
|
1 |
|
return $commands; |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* Get an object instance of the passed command |
253
|
|
|
* |
254
|
|
|
* @param string $command |
255
|
|
|
* |
256
|
|
|
* @return \Longman\TelegramBot\Commands\Command|null |
257
|
|
|
*/ |
258
|
1 |
|
public function getCommandObject($command) |
259
|
|
|
{ |
260
|
1 |
|
$which = ['System']; |
261
|
1 |
|
$this->isAdmin() && $which[] = 'Admin'; |
262
|
1 |
|
$which[] = 'User'; |
263
|
|
|
|
264
|
1 |
|
foreach ($which as $auth) { |
265
|
1 |
|
$command_namespace = __NAMESPACE__ . '\\Commands\\' . $auth . 'Commands\\' . $this->ucfirstUnicode($command) . 'Command'; |
266
|
1 |
|
if (class_exists($command_namespace)) { |
267
|
1 |
|
return new $command_namespace($this, $this->update); |
268
|
|
|
} |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
return null; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* Set custom input string for debug purposes |
276
|
|
|
* |
277
|
|
|
* @param string $input (json format) |
278
|
|
|
* |
279
|
|
|
* @return \Longman\TelegramBot\Telegram |
280
|
|
|
*/ |
281
|
|
|
public function setCustomInput($input) |
282
|
|
|
{ |
283
|
|
|
$this->input = $input; |
284
|
|
|
|
285
|
|
|
return $this; |
286
|
|
|
} |
287
|
|
|
|
288
|
|
|
/** |
289
|
|
|
* Get custom input string for debug purposes |
290
|
|
|
* |
291
|
|
|
* @return string |
292
|
|
|
*/ |
293
|
|
|
public function getCustomInput() |
294
|
|
|
{ |
295
|
|
|
return $this->input; |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
/** |
299
|
|
|
* Get the ServerResponse of the last Command execution |
300
|
|
|
* |
301
|
|
|
* @return \Longman\TelegramBot\Entities\ServerResponse |
302
|
|
|
*/ |
303
|
|
|
public function getLastCommandResponse() |
304
|
|
|
{ |
305
|
|
|
return $this->last_command_response; |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
/** |
309
|
|
|
* Handle getUpdates method |
310
|
|
|
* |
311
|
|
|
* @param int|null $limit |
312
|
|
|
* @param int|null $timeout |
313
|
|
|
* |
314
|
|
|
* @return \Longman\TelegramBot\Entities\ServerResponse |
315
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
316
|
|
|
*/ |
317
|
|
|
public function handleGetUpdates($limit = null, $timeout = null) |
318
|
|
|
{ |
319
|
|
|
if (empty($this->bot_username)) { |
320
|
|
|
throw new TelegramException('Bot Username is not defined!'); |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
if (!DB::isDbConnected()) { |
324
|
|
|
return new ServerResponse( |
325
|
|
|
[ |
326
|
|
|
'ok' => false, |
327
|
|
|
'description' => 'getUpdates needs MySQL connection!', |
328
|
|
|
], |
329
|
|
|
$this->bot_username |
330
|
|
|
); |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
//Take custom input into account. |
334
|
|
|
if ($custom_input = $this->getCustomInput()) { |
335
|
|
|
$response = new ServerResponse(json_decode($custom_input, true), $this->bot_username); |
336
|
|
|
} else { |
337
|
|
|
//DB Query |
338
|
|
|
$last_update = DB::selectTelegramUpdate(1); |
339
|
|
|
$last_update = reset($last_update); |
340
|
|
|
|
341
|
|
|
//As explained in the telegram bot api documentation |
342
|
|
|
$offset = isset($last_update['id']) ? $last_update['id'] + 1 : null; |
343
|
|
|
|
344
|
|
|
$response = Request::getUpdates( |
345
|
|
|
[ |
346
|
|
|
'offset' => $offset, |
347
|
|
|
'limit' => $limit, |
348
|
|
|
'timeout' => $timeout, |
349
|
|
|
] |
350
|
|
|
); |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
if ($response->isOk()) { |
354
|
|
|
//Process all updates |
355
|
|
|
/** @var Update $result */ |
356
|
|
|
foreach ((array) $response->getResult() as $result) { |
357
|
|
|
$this->processUpdate($result); |
358
|
|
|
} |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
return $response; |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
/** |
365
|
|
|
* Handle bot request from webhook |
366
|
|
|
* |
367
|
|
|
* @return bool |
368
|
|
|
* |
369
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
370
|
|
|
*/ |
371
|
|
|
public function handle() |
372
|
|
|
{ |
373
|
|
|
if (empty($this->bot_username)) { |
374
|
|
|
throw new TelegramException('Bot Username is not defined!'); |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
$this->input = Request::getInput(); |
378
|
|
|
|
379
|
|
|
if (empty($this->input)) { |
380
|
|
|
throw new TelegramException('Input is empty!'); |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
$post = json_decode($this->input, true); |
384
|
|
|
if (empty($post)) { |
385
|
|
|
throw new TelegramException('Invalid JSON!'); |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
if ($response = $this->processUpdate(new Update($post, $this->bot_username))) { |
389
|
|
|
return $response->isOk(); |
390
|
|
|
} |
391
|
|
|
|
392
|
|
|
return false; |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
/** |
396
|
|
|
* Get the command name from the command type |
397
|
|
|
* |
398
|
|
|
* @param string $type |
399
|
|
|
* |
400
|
|
|
* @return string |
401
|
|
|
*/ |
402
|
|
|
protected function getCommandFromType($type) |
403
|
|
|
{ |
404
|
|
|
return $this->ucfirstUnicode(str_replace('_', '', $type)); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
/** |
408
|
|
|
* Process bot Update request |
409
|
|
|
* |
410
|
|
|
* @param \Longman\TelegramBot\Entities\Update $update |
411
|
|
|
* |
412
|
|
|
* @return \Longman\TelegramBot\Entities\ServerResponse |
413
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
414
|
|
|
*/ |
415
|
|
|
public function processUpdate(Update $update) |
416
|
|
|
{ |
417
|
|
|
$this->update = $update; |
418
|
|
|
|
419
|
|
|
//If all else fails, it's a generic message. |
420
|
|
|
$command = 'genericmessage'; |
421
|
|
|
|
422
|
|
|
$update_type = $this->update->getUpdateType(); |
423
|
|
|
if (in_array($update_type, ['edited_message', 'channel_post', 'edited_channel_post', 'inline_query', 'chosen_inline_result', 'callback_query'], true)) { |
424
|
|
|
$command = $this->getCommandFromType($update_type); |
425
|
|
|
} elseif ($update_type === 'message') { |
426
|
|
|
$message = $this->update->getMessage(); |
427
|
|
|
|
428
|
|
|
//Load admin commands |
429
|
|
|
if ($this->isAdmin()) { |
430
|
|
|
$this->addCommandsPath(BASE_COMMANDS_PATH . '/AdminCommands', false); |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
$type = $message->getType(); |
434
|
|
|
if ($type === 'command') { |
435
|
|
|
$command = $message->getCommand(); |
436
|
|
|
} elseif (in_array($type, [ |
437
|
|
|
'channel_chat_created', |
438
|
|
|
'delete_chat_photo', |
439
|
|
|
'group_chat_created', |
440
|
|
|
'left_chat_member', |
441
|
|
|
'migrate_from_chat_id', |
442
|
|
|
'migrate_to_chat_id', |
443
|
|
|
'new_chat_member', |
444
|
|
|
'new_chat_photo', |
445
|
|
|
'new_chat_title', |
446
|
|
|
'pinned_message', |
447
|
|
|
'supergroup_chat_created', |
448
|
|
|
], true) |
449
|
|
|
) { |
450
|
|
|
$command = $this->getCommandFromType($type); |
451
|
|
|
} |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
//Make sure we have an up-to-date command list |
455
|
|
|
//This is necessary to "require" all the necessary command files! |
456
|
|
|
$this->getCommandsList(); |
457
|
|
|
|
458
|
|
|
DB::insertRequest($this->update); |
459
|
|
|
|
460
|
|
|
return $this->executeCommand($command); |
|
|
|
|
461
|
|
|
} |
462
|
|
|
|
463
|
|
|
/** |
464
|
|
|
* Execute /command |
465
|
|
|
* |
466
|
|
|
* @param string $command |
467
|
|
|
* |
468
|
|
|
* @return mixed |
469
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
470
|
|
|
*/ |
471
|
|
|
public function executeCommand($command) |
472
|
|
|
{ |
473
|
|
|
$command_obj = $this->getCommandObject($command); |
474
|
|
|
|
475
|
|
|
if (!$command_obj || !$command_obj->isEnabled()) { |
476
|
|
|
//Failsafe in case the Generic command can't be found |
477
|
|
|
if ($command === 'Generic') { |
478
|
|
|
throw new TelegramException('Generic command missing!'); |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
//Handle a generic command or non existing one |
482
|
|
|
$this->last_command_response = $this->executeCommand('Generic'); |
483
|
|
|
} else { |
484
|
|
|
//Botan.io integration, make sure only the actual command user executed is reported |
485
|
|
|
if ($this->botan_enabled) { |
486
|
|
|
Botan::lock($command); |
487
|
|
|
} |
488
|
|
|
|
489
|
|
|
//execute() method is executed after preExecute() |
490
|
|
|
//This is to prevent executing a DB query without a valid connection |
491
|
|
|
$this->last_command_response = $command_obj->preExecute(); |
492
|
|
|
|
493
|
|
|
//Botan.io integration, send report after executing the command |
494
|
|
|
if ($this->botan_enabled) { |
495
|
|
|
Botan::track($this->update, $command); |
496
|
|
|
} |
497
|
|
|
} |
498
|
|
|
|
499
|
|
|
return $this->last_command_response; |
500
|
|
|
} |
501
|
|
|
|
502
|
|
|
/** |
503
|
|
|
* Sanitize Command |
504
|
|
|
* |
505
|
|
|
* @param string $command |
506
|
|
|
* |
507
|
|
|
* @return string |
508
|
|
|
*/ |
509
|
1 |
|
protected function sanitizeCommand($command) |
510
|
|
|
{ |
511
|
1 |
|
return str_replace(' ', '', $this->ucwordsUnicode(str_replace('_', ' ', $command))); |
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
/** |
515
|
|
|
* Enable a single Admin account |
516
|
|
|
* |
517
|
|
|
* @param integer $admin_id Single admin id |
518
|
|
|
* |
519
|
|
|
* @return \Longman\TelegramBot\Telegram |
520
|
|
|
*/ |
521
|
1 |
|
public function enableAdmin($admin_id) |
522
|
|
|
{ |
523
|
1 |
|
if (is_int($admin_id) && $admin_id > 0 && !in_array($admin_id, $this->admins_list, true)) { |
524
|
1 |
|
$this->admins_list[] = $admin_id; |
525
|
|
|
} else { |
526
|
1 |
|
TelegramLog::error('Invalid value "%s" for admin.', $admin_id); |
527
|
|
|
} |
528
|
|
|
|
529
|
1 |
|
return $this; |
530
|
|
|
} |
531
|
|
|
|
532
|
|
|
/** |
533
|
|
|
* Enable a list of Admin Accounts |
534
|
|
|
* |
535
|
|
|
* @param array $admin_ids List of admin ids |
536
|
|
|
* |
537
|
|
|
* @return \Longman\TelegramBot\Telegram |
538
|
|
|
*/ |
539
|
1 |
|
public function enableAdmins(array $admin_ids) |
540
|
|
|
{ |
541
|
1 |
|
foreach ($admin_ids as $admin_id) { |
542
|
1 |
|
$this->enableAdmin($admin_id); |
543
|
|
|
} |
544
|
|
|
|
545
|
1 |
|
return $this; |
546
|
|
|
} |
547
|
|
|
|
548
|
|
|
/** |
549
|
|
|
* Get list of admins |
550
|
|
|
* |
551
|
|
|
* @return array |
552
|
|
|
*/ |
553
|
1 |
|
public function getAdminList() |
554
|
|
|
{ |
555
|
1 |
|
return $this->admins_list; |
556
|
|
|
} |
557
|
|
|
|
558
|
|
|
/** |
559
|
|
|
* Check if the passed user is an admin |
560
|
|
|
* |
561
|
|
|
* If no user id is passed, the current update is checked for a valid message sender. |
562
|
|
|
* |
563
|
|
|
* @param int|null $user_id |
564
|
|
|
* |
565
|
|
|
* @return bool |
566
|
|
|
*/ |
567
|
1 |
|
public function isAdmin($user_id = null) |
568
|
|
|
{ |
569
|
1 |
|
if ($user_id === null && $this->update !== null) { |
570
|
|
|
//Try to figure out if the user is an admin |
571
|
|
|
$update_methods = [ |
572
|
|
|
'getMessage', |
573
|
|
|
'getEditedMessage', |
574
|
|
|
'getChannelPost', |
575
|
|
|
'getEditedChannelPost', |
576
|
|
|
'getInlineQuery', |
577
|
|
|
'getChosenInlineResult', |
578
|
|
|
'getCallbackQuery', |
579
|
|
|
]; |
580
|
|
|
foreach ($update_methods as $update_method) { |
581
|
|
|
$object = call_user_func([$this->update, $update_method]); |
582
|
|
|
if ($object !== null && $from = $object->getFrom()) { |
583
|
|
|
$user_id = $from->getId(); |
584
|
|
|
break; |
585
|
|
|
} |
586
|
|
|
} |
587
|
|
|
} |
588
|
|
|
|
589
|
1 |
|
return ($user_id === null) ? false : in_array($user_id, $this->admins_list, true); |
590
|
|
|
} |
591
|
|
|
|
592
|
|
|
/** |
593
|
|
|
* Check if user required the db connection |
594
|
|
|
* |
595
|
|
|
* @return bool |
596
|
|
|
*/ |
597
|
|
|
public function isDbEnabled() |
598
|
|
|
{ |
599
|
|
|
if ($this->mysql_enabled) { |
600
|
|
|
return true; |
601
|
|
|
} else { |
602
|
|
|
return false; |
603
|
|
|
} |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
/** |
607
|
|
|
* Add a single custom commands path |
608
|
|
|
* |
609
|
|
|
* @param string $path Custom commands path to add |
610
|
|
|
* @param bool $before If the path should be prepended or appended to the list |
611
|
|
|
* |
612
|
|
|
* @return \Longman\TelegramBot\Telegram |
613
|
|
|
*/ |
614
|
30 |
|
public function addCommandsPath($path, $before = true) |
615
|
|
|
{ |
616
|
30 |
|
if (!is_dir($path)) { |
617
|
1 |
|
TelegramLog::error('Commands path "%s" does not exist.', $path); |
618
|
30 |
|
} elseif (!in_array($path, $this->commands_paths, true)) { |
619
|
30 |
|
if ($before) { |
620
|
30 |
|
array_unshift($this->commands_paths, $path); |
621
|
|
|
} else { |
622
|
|
|
$this->commands_paths[] = $path; |
623
|
|
|
} |
624
|
|
|
} |
625
|
|
|
|
626
|
30 |
|
return $this; |
627
|
|
|
} |
628
|
|
|
|
629
|
|
|
/** |
630
|
|
|
* Add multiple custom commands paths |
631
|
|
|
* |
632
|
|
|
* @param array $paths Custom commands paths to add |
633
|
|
|
* @param bool $before If the paths should be prepended or appended to the list |
634
|
|
|
* |
635
|
|
|
* @return \Longman\TelegramBot\Telegram |
636
|
|
|
*/ |
637
|
1 |
|
public function addCommandsPaths(array $paths, $before = true) |
638
|
|
|
{ |
639
|
1 |
|
foreach ($paths as $path) { |
640
|
1 |
|
$this->addCommandsPath($path, $before); |
641
|
|
|
} |
642
|
|
|
|
643
|
1 |
|
return $this; |
644
|
|
|
} |
645
|
|
|
|
646
|
|
|
/** |
647
|
|
|
* Return the list of commands paths |
648
|
|
|
* |
649
|
|
|
* @return array |
650
|
|
|
*/ |
651
|
1 |
|
public function getCommandsPaths() |
652
|
|
|
{ |
653
|
1 |
|
return $this->commands_paths; |
654
|
|
|
} |
655
|
|
|
|
656
|
|
|
/** |
657
|
|
|
* Set custom upload path |
658
|
|
|
* |
659
|
|
|
* @param string $path Custom upload path |
660
|
|
|
* |
661
|
|
|
* @return \Longman\TelegramBot\Telegram |
662
|
|
|
*/ |
663
|
|
|
public function setUploadPath($path) |
664
|
|
|
{ |
665
|
|
|
$this->upload_path = $path; |
666
|
|
|
|
667
|
|
|
return $this; |
668
|
|
|
} |
669
|
|
|
|
670
|
|
|
/** |
671
|
|
|
* Get custom upload path |
672
|
|
|
* |
673
|
|
|
* @return string |
674
|
|
|
*/ |
675
|
|
|
public function getUploadPath() |
676
|
|
|
{ |
677
|
|
|
return $this->upload_path; |
678
|
|
|
} |
679
|
|
|
|
680
|
|
|
/** |
681
|
|
|
* Set custom download path |
682
|
|
|
* |
683
|
|
|
* @param string $path Custom download path |
684
|
|
|
* |
685
|
|
|
* @return \Longman\TelegramBot\Telegram |
686
|
|
|
*/ |
687
|
|
|
public function setDownloadPath($path) |
688
|
|
|
{ |
689
|
|
|
$this->download_path = $path; |
690
|
|
|
|
691
|
|
|
return $this; |
692
|
|
|
} |
693
|
|
|
|
694
|
|
|
/** |
695
|
|
|
* Get custom download path |
696
|
|
|
* |
697
|
|
|
* @return string |
698
|
|
|
*/ |
699
|
|
|
public function getDownloadPath() |
700
|
|
|
{ |
701
|
|
|
return $this->download_path; |
702
|
|
|
} |
703
|
|
|
|
704
|
|
|
/** |
705
|
|
|
* Set command config |
706
|
|
|
* |
707
|
|
|
* Provide further variables to a particular commands. |
708
|
|
|
* For example you can add the channel name at the command /sendtochannel |
709
|
|
|
* Or you can add the api key for external service. |
710
|
|
|
* |
711
|
|
|
* @param string $command |
712
|
|
|
* @param array $config |
713
|
|
|
* |
714
|
|
|
* @return \Longman\TelegramBot\Telegram |
715
|
|
|
*/ |
716
|
14 |
|
public function setCommandConfig($command, array $config) |
717
|
|
|
{ |
718
|
14 |
|
$this->commands_config[$command] = $config; |
719
|
|
|
|
720
|
14 |
|
return $this; |
721
|
|
|
} |
722
|
|
|
|
723
|
|
|
/** |
724
|
|
|
* Get command config |
725
|
|
|
* |
726
|
|
|
* @param string $command |
727
|
|
|
* |
728
|
|
|
* @return array |
729
|
|
|
*/ |
730
|
15 |
|
public function getCommandConfig($command) |
731
|
|
|
{ |
732
|
15 |
|
return isset($this->commands_config[$command]) ? $this->commands_config[$command] : []; |
733
|
|
|
} |
734
|
|
|
|
735
|
|
|
/** |
736
|
|
|
* Get API key |
737
|
|
|
* |
738
|
|
|
* @return string |
739
|
|
|
*/ |
740
|
1 |
|
public function getApiKey() |
741
|
|
|
{ |
742
|
1 |
|
return $this->api_key; |
743
|
|
|
} |
744
|
|
|
|
745
|
|
|
/** |
746
|
|
|
* Get Bot name |
747
|
|
|
* |
748
|
|
|
* @return string |
749
|
|
|
*/ |
750
|
1 |
|
public function getBotUsername() |
751
|
|
|
{ |
752
|
1 |
|
return $this->bot_username; |
753
|
|
|
} |
754
|
|
|
|
755
|
|
|
/** |
756
|
|
|
* Get Bot Id |
757
|
|
|
* |
758
|
|
|
* @return string |
759
|
|
|
*/ |
760
|
|
|
public function getBotId() |
761
|
|
|
{ |
762
|
|
|
return $this->bot_id; |
763
|
|
|
} |
764
|
|
|
|
765
|
|
|
/** |
766
|
|
|
* Get Version |
767
|
|
|
* |
768
|
|
|
* @return string |
769
|
|
|
*/ |
770
|
|
|
public function getVersion() |
771
|
|
|
{ |
772
|
|
|
return $this->version; |
773
|
|
|
} |
774
|
|
|
|
775
|
|
|
/** |
776
|
|
|
* Set Webhook for bot |
777
|
|
|
* |
778
|
|
|
* @param string $url |
779
|
|
|
* @param array $data Optional parameters. |
780
|
|
|
* |
781
|
|
|
* @return \Longman\TelegramBot\Entities\ServerResponse |
782
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
783
|
|
|
*/ |
784
|
|
|
public function setWebhook($url, array $data = []) |
785
|
|
|
{ |
786
|
|
|
if (empty($url)) { |
787
|
|
|
throw new TelegramException('Hook url is empty!'); |
788
|
|
|
} |
789
|
|
|
|
790
|
|
|
$result = Request::setWebhook($url, $data); |
791
|
|
|
|
792
|
|
View Code Duplication |
if (!$result->isOk()) { |
|
|
|
|
793
|
|
|
throw new TelegramException( |
794
|
|
|
'Webhook was not set! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription() |
795
|
|
|
); |
796
|
|
|
} |
797
|
|
|
|
798
|
|
|
return $result; |
799
|
|
|
} |
800
|
|
|
|
801
|
|
|
/** |
802
|
|
|
* Delete any assigned webhook |
803
|
|
|
* |
804
|
|
|
* @return mixed |
805
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
806
|
|
|
*/ |
807
|
|
|
public function deleteWebhook() |
808
|
|
|
{ |
809
|
|
|
$result = Request::deleteWebhook(); |
810
|
|
|
|
811
|
|
View Code Duplication |
if (!$result->isOk()) { |
|
|
|
|
812
|
|
|
throw new TelegramException( |
813
|
|
|
'Webhook was not deleted! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription() |
814
|
|
|
); |
815
|
|
|
} |
816
|
|
|
|
817
|
|
|
return $result; |
818
|
|
|
} |
819
|
|
|
|
820
|
|
|
/** |
821
|
|
|
* Replace function `ucwords` for UTF-8 characters in the class definition and commands |
822
|
|
|
* |
823
|
|
|
* @param string $str |
824
|
|
|
* @param string $encoding (default = 'UTF-8') |
825
|
|
|
* |
826
|
|
|
* @return string |
827
|
|
|
*/ |
828
|
1 |
|
protected function ucwordsUnicode($str, $encoding = 'UTF-8') |
829
|
|
|
{ |
830
|
1 |
|
return mb_convert_case($str, MB_CASE_TITLE, $encoding); |
831
|
|
|
} |
832
|
|
|
|
833
|
|
|
/** |
834
|
|
|
* Replace function `ucfirst` for UTF-8 characters in the class definition and commands |
835
|
|
|
* |
836
|
|
|
* @param string $str |
837
|
|
|
* @param string $encoding (default = 'UTF-8') |
838
|
|
|
* |
839
|
|
|
* @return string |
840
|
|
|
*/ |
841
|
1 |
|
protected function ucfirstUnicode($str, $encoding = 'UTF-8') |
842
|
|
|
{ |
843
|
|
|
return |
844
|
1 |
|
mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding) |
845
|
1 |
|
. mb_strtolower(mb_substr($str, 1, mb_strlen($str), $encoding), $encoding); |
846
|
|
|
} |
847
|
|
|
|
848
|
|
|
/** |
849
|
|
|
* Enable Botan.io integration |
850
|
|
|
* |
851
|
|
|
* @param string $token |
852
|
|
|
* @param array $options |
853
|
|
|
* |
854
|
|
|
* @return \Longman\TelegramBot\Telegram |
855
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
856
|
|
|
*/ |
857
|
|
|
public function enableBotan($token, array $options = []) |
858
|
|
|
{ |
859
|
|
|
Botan::initializeBotan($token, $options); |
860
|
|
|
$this->botan_enabled = true; |
861
|
|
|
|
862
|
|
|
return $this; |
863
|
|
|
} |
864
|
|
|
|
865
|
|
|
/** |
866
|
|
|
* Enable requests limiter |
867
|
|
|
* |
868
|
|
|
* @param array $options |
869
|
|
|
* |
870
|
|
|
* @return \Longman\TelegramBot\Telegram |
871
|
|
|
*/ |
872
|
|
|
public function enableLimiter(array $options = []) |
873
|
|
|
{ |
874
|
|
|
Request::setLimiter(true, $options); |
875
|
|
|
|
876
|
|
|
return $this; |
877
|
|
|
} |
878
|
|
|
|
879
|
|
|
/** |
880
|
|
|
* Run provided commands |
881
|
|
|
* |
882
|
|
|
* @param array $commands |
883
|
|
|
* |
884
|
|
|
* @throws TelegramException |
885
|
|
|
*/ |
886
|
|
|
public function runCommands($commands) |
887
|
|
|
{ |
888
|
|
|
if (!is_array($commands) || empty($commands)) { |
889
|
|
|
throw new TelegramException('No command(s) provided!'); |
890
|
|
|
} |
891
|
|
|
|
892
|
|
|
$this->run_commands = true; |
893
|
|
|
$this->botan_enabled = false; // Force disable Botan.io integration, we don't want to track self-executed commands! |
894
|
|
|
|
895
|
|
|
$result = Request::getMe()->getResult(); |
896
|
|
|
|
897
|
|
|
if (!$result->getId()) { |
898
|
|
|
throw new TelegramException('Received empty/invalid getMe result!'); |
899
|
|
|
} |
900
|
|
|
|
901
|
|
|
$bot_id = $result->getId(); |
902
|
|
|
$bot_name = $result->getFirstName(); |
903
|
|
|
$bot_username = $result->getUsername(); |
904
|
|
|
|
905
|
|
|
$this->enableAdmin($bot_id); // Give bot access to admin commands |
906
|
|
|
$this->getCommandsList(); // Load full commands list |
907
|
|
|
|
908
|
|
|
foreach ($commands as $command) { |
909
|
|
|
$this->update = new Update( |
910
|
|
|
[ |
911
|
|
|
'update_id' => 0, |
912
|
|
|
'message' => [ |
913
|
|
|
'message_id' => 0, |
914
|
|
|
'from' => [ |
915
|
|
|
'id' => $bot_id, |
916
|
|
|
'first_name' => $bot_name, |
917
|
|
|
'username' => $bot_username, |
918
|
|
|
], |
919
|
|
|
'date' => time(), |
920
|
|
|
'chat' => [ |
921
|
|
|
'id' => $bot_id, |
922
|
|
|
'type' => 'private', |
923
|
|
|
], |
924
|
|
|
'text' => $command, |
925
|
|
|
], |
926
|
|
|
] |
927
|
|
|
); |
928
|
|
|
|
929
|
|
|
$this->executeCommand($this->update->getMessage()->getCommand()); |
|
|
|
|
930
|
|
|
} |
931
|
|
|
} |
932
|
|
|
|
933
|
|
|
/** |
934
|
|
|
* Is this session initiated by runCommands() |
935
|
|
|
* |
936
|
|
|
* @return bool |
937
|
|
|
*/ |
938
|
|
|
public function isRunCommands() |
939
|
|
|
{ |
940
|
|
|
return $this->run_commands; |
941
|
|
|
} |
942
|
|
|
} |
943
|
|
|
|
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.