Passed
Push — master ( 7ecda6...2093cf )
by Armando
04:22 queued 02:31
created

Command::removeNonPrivateMessage()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

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