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