Completed
Push — master ( 81c6be...588ef8 )
by Danilo
02:39
created

Bot::initBot()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
3
namespace PhpBotFramework;
4
5
use Exceptions\BotException;
6
7
use Entities\InlineKeyboard;
8
9
/**
10
 * \class Bot Bot
11
 * \brief Bot class to handle updates and commandes.
12
 * \details Class Bot to handle task like api request, or more specific api function(sendMessage, editMessageText, etc).
13
 * Usage example in webhook.php
14
 *
15
 */
16
class Bot extends Core\CoreBot {
17
18
    use LongPolling,
19
        MessageCommand,
20
        CallbackCommand,
21
        DatabaseHandler,
22
        BotState,
23
        Localization;
24
25
    /**
26
     * \addtogroup Bot Bot
27
     * \brief Properties and methods to handle the TelegramBot.
28
     * \details Here are listed all the properties and methods that will help the developer create the basic bot functions.
29
     * @{
30
     */
31
32
    /** \brief Text received in messages */
33
    protected $_text;
34
35
    /** \brief Data received in callback query */
36
    protected $_data;
37
38
    /** \brief Query sent by the user in the inline query */
39
    protected $_query;
40
41
    /** \brief Store the inline keyboard */
42
    public $keyboard;
43
44
    /** \brief Pdo reference */
45
    public $pdo;
46
47
    /** \brief Redis connection */
48
    public $redis;
49
50
    /** @} */
51
52
53
    /**
54
     * \addtogroup Bot
55
     * @{
56
     */
57
58
    /**
59
     * \brief Construct an empy bot.
60
     * \details Construct a bot with commands, multilanguage and status.
61
     */
62
    public function __construct(string $token) {
63
64
        // Parent constructor
65
        parent::__construct($token);
66
67
        // Initialize to an empty array
68
        $this->_message_commands = [];
69
        $this->_callback_commands = [];
70
71
        $this->keyboard = new InlineKeyboard($this);
72
73
    }
74
75
    /** \brief Descruct the class. */
76
    public function __destruct() {
77
        // Close redis connection if it is open
78
        if (isset($this->redis)) {
79
80
            $this->redis->close();
81
82
        }
83
84
    }
85
86
    /**
87
     * \brief Get the text of the message, if set (for updates of type "message").
88
     * @return Text of the message, empty string if not set.
89
     */
90
    public function getMessageText() : string {
91
92
        if (isset($this->_text)) {
93
94
            return $this->_text;
95
96
        }
97
98
        return '';
99
100
    }
101
102
    /**
103
     * \brief Get the data of callback query, if set (for updates of type "callback_query").
104
     * @return Data of the callback query, empty string if not set.
105
     */
106
    public function getCallbackData() : string {
107
108
        if (isset($this->_data)) {
109
110
            return $this->_data;
111
112
        }
113
114
        return '';
115
116
    }
117
118
    /**
119
     * \brief Get the query received from the inline query (for updates of type "inline_query").
120
     * @return The query sent by the user, throw exception if the current update is not an inline query.
121
     */
122
    public function getInlineQuery() : string {
123
124
        if (isset($this->_query)) {
125
126
            return $this->_query;
127
128
        }
129
130
        throw new BotException("Query from inline query is not set: wrong update type");
131
    }
132
133
    /**
134
     * \brief Get update and process it.
135
     * \details Call this method if you are using webhook.
136
     * It will get update from php::\input, check it and then process it using processUpdate.
137
     */
138
    public function processWebhookUpdate() {
139
140
        $this->initBot();
141
142
        $this->processUpdate(json_decode(file_get_contents('php://input'), true));
143
144
    }
145
146
    /** @} */
147
148
    /**
149
     * \addtogroup Core Core(Internal)
150
     * @{
151
     */
152
153
    /**
154
     * \brief Init variables to skip parsing commands if there aren't any.
155
     * \details Called internnaly by
156
     * - <code>getUpdatesLocal</code>
157
     * - <code>getUpdatesRedis</code>
158
     * - <code>getUpdatesDatabase</code>
159
     * - <code>processWebhookUpdate</code>
160
     */
161
    private function initBot() {
162
163
        // Are there message commands?
164
        $this->_message_commands_set = !empty($this->_message_commands);
165
166
        // Are there callback commands?
167
        $this->_callback_commands_set = !empty($this->_callback_commands);
168
169
    }
170
171
    /**
172
     * \brief Dispatch each update to the right method (processMessage, processCallbackQuery, etc).
173
     * \details Set $chat_id for each update, $text, $data and $query are set for each update that contains them.
174
     * It also calls commands for each updates, before process methods.
175
     * @param $update Reference to the update received.
176
     * @return The id of the update processed.
177
     */
178
    public function processUpdate(array $update) : int {
179
180
        if (isset($update['message'])) {
181
182
            // Set data from the message
183
            $this->_chat_id = $update['message']['chat']['id'];
184
185
            // If the message contains text
186
            if (isset($update['message']['text'])) {
187
188
                $this->_text = $update['message']['text'];
189
190
            }
191
192
            // If there are commands set by the user
193
            // and there are bot commands in the message, checking message entities
194
            if ($this->_message_commands_set && isset($update['message']['entities']) && $update['message']['entities'][0]['type'] === 'bot_command') {
195
196
                // The lenght of the command
197
                $length = $update['message']['entities'][0]['length'];
198
199
                // Offset of the command
200
                $offset = $update['message']['entities'][0]['offset'];
201
202
                // For each command added by the user
203
                foreach ($this->_message_commands as $trigger) {
204
205
                    // If the current command is a regex
206
                    if ($trigger['regex_active']) {
207
208
                        // Use preg_match to check if it is true
209
                        $matched = preg_match('/' . $trigger['regex_rule'] . '/', substr($update['message']['text'], $offset + 1, $length));
210
211
                        // else check if the command sent by the user is the same as the one we are expecting
212
                    } else if ($trigger['length'] == $length && mb_strpos($trigger['command'], $update['message']['text'], $offset) !== false) {
213
214
                        // We found a valid command
215
                        $matched = true;
216
217
                    } else {
218
219
                        // We did not
220
                        $matched = false;
221
222
                    }
223
224
                    // Check the results for the current command
225
                    if ($matched) {
226
227
                        // Execute script,
228
                        $trigger['script']($this, $update['message']);
229
230
                        // clear text variable
231
                        unset($this->_text);
232
233
                        // and return the id of the current update to stop processing this update
234
                        return $update['update_id'];
235
236
                    }
237
238
                }
239
240
            }
241
242
            // And process it
243
            $this->processMessage($update['message']);
244
245
            // clear text variable
246
            unset($this->_text);
247
248
            // If the update is a callback query
249
        } elseif (isset($update['callback_query'])) {
250
251
            // Set variables
252
            $this->_chat_id = $update['callback_query']['message']['chat']['id'];
253
            $this->_callback_query_id = $update['callback_query']['id'];
254
255
            // If data is set for the current callback query
256
            if (isset($update['callback_query']['data'])) {
257
258
                $this->_data = $update['callback_query']['data'];
259
260
            }
261
262
            // Check for callback commands
263
            if (isset($this->_data) && $this->_callback_commands_set) {
264
265
                // Parse all commands
266
                foreach ($this->_callback_commands as $trigger) {
267
268
                    // If command is found in callback data
269
                    if (strpos($trigger['data'], $this->_data) !== false) {
270
271
                        // Trigger the script
272
                        $trigger['script']($this, $update['callback_query']);
273
274
                        // Clear data
275
                        unset($this->_data);
276
                        unset($this->_callback_query_id);
277
278
                        // and return the id of the current update
279
                        return $update['update_id'];
280
281
                    }
282
283
                }
284
285
            }
286
287
            // Process the callback query through processCallbackQuery
288
            $this->processCallbackQuery($update['callback_query']);
289
290
            // Unset callback query variables
291
            unset($this->_callback_query_id);
292
            unset($this->_data);
293
294
        } elseif (isset($update['inline_query'])) {
295
296
            $this->_chat_id = $update['inline_query']['from']['id'];
297
            $this->_query = $update['inline_query']['query'];
298
            $this->_inline_query_id = $update['inline_query']['id'];
299
300
            $this->processInlineQuery($update['inline_query']);
301
302
            unset($this->_query);
303
            unset($this->_inline_query_id);
304
305
        } elseif (isset($update['channel_post'])) {
306
307
            // Set data from the post
308
            $this->_chat_id = $update['channel_post']['chat']['id'];
309
310
            $this->processChannelPost($update['channel_post']);
311
312
        } elseif (isset($update['edited_message'])) {
313
314
            $this->_chat_id = $update['edited_message']['chat']['id'];
315
316
            $this->processEditedMessage($update['edited_message']);
317
318
        } elseif (isset($update['edited_channel_post'])) {
319
320
            $this->_chat_id = $update['edited_channel_post']['chat']['id'];
321
322
            $this->processEditedChannelPost($update['edited_channel_post']);
323
324
        } elseif (isset($update['chosen_inline_result'])) {
325
326
            $this->_chat_id = $update['chosen_inline_result']['chat']['id'];
327
328
            $this->processChosenInlineResult($update['chosen_inline_result']);
329
330
        }
331
332
        return $update['update_id'];
333
334
    }
335
336
    /** @} */
337
338
    /**
339
     * \addtogroup Bot Bot
340
     * @{
341
     */
342
343
    /**
344
     * \brief Called every message received by the bot.
345
     * \details Override it to script the bot answer for each message.
346
     * <code>$chat_id</code> and <code>$text</code>, if the message contains text(use getMessageText() to access it), set inside of this function.
347
     * @param $message Reference to the message received.
348
     */
349
    protected function processMessage($message) {
350
351
    }
352
353
    /**
354
     * \brief Called every callback query received by the bot.
355
     * \details Override it to script the bot answer for each callback.
356
     * <code>$chat_id</code> and <code>$data</code>, if set in the callback query(use getCallbackData() to access it) set inside of this function.
357
     * @param $callback_query Reference to the callback query received.
358
     */
359
    protected function processCallbackQuery($callback_query) {
360
361
    }
362
363
    /**
364
     * \brief Called every inline query received by the bot.
365
     * \details Override it to script the bot answer for each inline query.
366
     * $chat_id and $query(use getInlineQuery() to access it) set inside of this function.
367
     * @param $inline_query Reference to the inline query received.
368
     */
369
    protected function processInlineQuery($inline_query) {
370
371
    }
372
373
    /**
374
     * \brief Called every chosen inline result received by the bot.
375
     * \details Override it to script the bot answer for each chosen inline result.
376
     * <code>$chat_id</code> set inside of this function.
377
     * @param $chosen_inline_result Reference to the chosen inline result received.
378
     */
379
    protected function processChosenInlineResult($chosen_inline_result) {
380
381
    }
382
383
    /**
384
     * \brief Called every chosen edited message received by the bot.
385
     * \details Override it to script the bot answer for each edited message.
386
     * <code>$chat_id</code> set inside of this function.
387
     * @param $edited_message The message edited by the user.
388
     */
389
    protected function processEditedMessage($edited_message) {
390
391
    }
392
393
    /**
394
     * \brief Called every new post in the channel where the bot is in.
395
     * \details Override it to script the bot answer for each post sent in a channel.
396
     * <code>$chat_id</code> set inside of this function.
397
     * @param $post The message sent in the channel.
398
     */
399
    protected function processChannelPost($post) {
400
401
    }
402
403
    /**
404
     * \brief Called every time a post get edited in the channel where the bot is in.
405
     * \details Override it to script the bot answer for each post edited  in a channel.
406
     * <code>$chat_id</code> set inside of this function.
407
     * @param $post The message edited in the channel.
408
     */
409
    protected function processEditedChannelPost($edited_post) {
410
411
    }
412
413
    /** @} */
414
415
}
416