Completed
Branch develop (340e70)
by Armando
03:17
created

BotManager::handleGetUpdatesLoop()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 16
rs 9.4285
cc 2
eloc 7
nc 2
nop 1
1
<?php
2
/**
3
 * This file is part of the TelegramBotManager package.
4
 *
5
 * (c) Armando Lüscher <[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 NPM\TelegramBotManager;
12
13
use Longman\TelegramBot\Entities;
14
use Longman\TelegramBot\Telegram;
15
use Longman\TelegramBot\TelegramLog;
16
17
/**
18
 * Class BotManager.php
19
 *
20
 * Leave all member variables public to allow easy modification.
21
 *
22
 * @package NPM\TelegramBotManager
23
 */
24
class BotManager
25
{
26
    /**
27
     * @var Telegram
28
     */
29
    public $telegram;
30
31
    /**
32
     * @var string The output for testing, instead of echoing
33
     */
34
    public $test_output;
35
36
    /**
37
     * @var Params Object that manages the parameters.
38
     */
39
    private $params;
40
41
    /**
42
     * @var Action Object that contains the current action.
43
     */
44
    private $action;
45
46
    /**
47
     * BotManager constructor.
48
     *
49
     * @param array $params
50
     *
51
     * @throws \InvalidArgumentException
52
     */
53
    public function __construct(array $params)
54
    {
55
        $this->params = new Params($params);
56
        $this->action = new Action($this->params->getScriptParam('a'));
57
    }
58
59
    public function getParams()
60
    {
61
        return $this->params;
62
    }
63
64
    public function getAction()
65
    {
66
        return $this->action;
67
    }
68
69
    /**
70
     * Run this thing in all its glory!
71
     *
72
     * @throws \InvalidArgumentException
73
     */
74
    public function run()
75
    {
76
        // Initialise logging.
77
        $this->initLogging();
78
79
        // Make sure this is a valid call.
80
        $this->validateSecret();
81
82
        // Set up a new Telegram instance.
83
        $this->telegram = new Telegram(
84
            $this->params->getBotParam('api_key'),
85
            $this->params->getBotParam('botname')
86
        );
87
88
        if ($this->action->isAction(['set', 'unset', 'reset'])) {
89
            $this->validateAndSetWebhook();
90
        } elseif ($this->action->isAction('handle')) {
91
            // Set any extras.
92
            $this->setBotExtras();
93
            $this->handleRequest();
94
        }
95
96
        return $this;
97
    }
98
99
    /**
100
     * Initialise all loggers.
101
     */
102
    public function initLogging()
103
    {
104
        $logging = $this->params->getBotParam('logging');
105
        if (is_array($logging)) {
106
            /** @var array $logging */
107
            foreach ($logging as $logger => $logfile) {
108
                ('debug' === $logger) && TelegramLog::initDebugLog($logfile);
109
                ('error' === $logger) && TelegramLog::initErrorLog($logfile);
110
                ('update' === $logger) && TelegramLog::initUpdateLog($logfile);
111
            }
112
        }
113
114
        return $this;
115
    }
116
117
    /**
118
     * Make sure the passed secret is valid.
119
     *
120
     * @param bool $force Force validation, even on CLI.
121
     *
122
     * @return $this
123
     * @throws \InvalidArgumentException
124
     */
125
    public function validateSecret($force = false)
126
    {
127
        // If we're running from CLI, secret isn't necessary.
128
        if ($force || 'cli' !== PHP_SAPI) {
129
            $secret    = $this->params->getBotParam('secret');
130
            $secretGet = $this->params->getScriptParam('s');
131
            if ($secretGet !== $secret) {
132
                throw new \InvalidArgumentException('Invalid access');
133
            }
134
        }
135
136
        return $this;
137
    }
138
139
    /**
140
     * Make sure the webhook is valid and perform the requested webhook operation.
141
     *
142
     * @throws \InvalidArgumentException
143
     */
144
    public function validateAndSetWebhook()
145
    {
146
        $webhook = $this->params->getBotParam('webhook');
147
        $selfcrt = $this->params->getBotParam('selfcrt');
148
        if (empty($webhook) && $this->action->isAction(['set', 'reset'])) {
149
            throw new \InvalidArgumentException('Invalid webhook');
150
        }
151
152
        if ($this->action->isAction(['unset', 'reset'])) {
153
            $this->test_output = $this->telegram->unsetWebHook()->getDescription();
154
        }
155
        if ($this->action->isAction(['set', 'reset'])) {
156
            $this->test_output = $this->telegram->setWebHook(
157
                $webhook . '?a=handle&s=' . $this->params->getBotParam('secret'),
158
                $selfcrt
159
            )->getDescription();
160
        }
161
162
        (@constant('PHPUNIT_TEST') !== true) && print($this->test_output . PHP_EOL);
163
164
        return $this;
165
    }
166
167
    /**
168
     * Set any extra bot features that have been assigned on construction.
169
     *
170
     * @return $this
171
     */
172
    public function setBotExtras()
173
    {
174
        ($v = $this->params->getBotParam('admins')) && $this->telegram->enableAdmins($v);
175
        ($v = $this->params->getBotParam('mysql')) && $this->telegram->enableMySql($v);
176
        ($v = $this->params->getBotParam('botan_token')) && $this->telegram->enableBotan($v);
177
        ($v = $this->params->getBotParam('commands_paths')) && $this->telegram->addCommandsPaths($v);
178
        ($v = $this->params->getBotParam('custom_input')) && $this->telegram->setCustomInput($v);
179
        ($v = $this->params->getBotParam('download_path')) && $this->telegram->setDownloadPath($v);
180
        ($v = $this->params->getBotParam('upload_path')) && $this->telegram->setUploadPath($v);
181
182
        $command_configs = $this->params->getBotParam('command_configs');
183
        if (is_array($command_configs)) {
184
            /** @var array $command_configs */
185
            foreach ($command_configs as $command => $config) {
186
                $this->telegram->setCommandConfig($command, $config);
187
            }
188
        }
189
190
        return $this;
191
    }
192
193
    /**
194
     * Handle the request, which calls either the Webhook or getUpdates method respectively.
195
     *
196
     * @throws \InvalidArgumentException
197
     */
198
    public function handleRequest()
199
    {
200
        if (empty($this->params->getBotParam('webhook'))) {
201
            if ($loop_time = $this->getLoopTime()) {
202
                $this->handleGetUpdatesLoop($loop_time);
203
            } else {
204
                $this->handleGetUpdates();
205
            }
206
        } else {
207
            $this->handleWebhook();
208
        }
209
210
        return $this;
211
    }
212
213
    /**
214
     * Get the number of seconds the script should loop.
215
     *
216
     * @return int
217
     */
218
    public function getLoopTime()
219
    {
220
        $loop_time = $this->params->getScriptParam('l');
221
222
        if (null === $loop_time) {
223
            return 0;
224
        }
225
226
        if ('' === trim($loop_time)) {
227
            return 604800; // Default to 7 days.
228
        }
229
230
        return max(0, (int)$loop_time);
231
    }
232
233
    /**
234
     * Loop the getUpdates method for the passed amount of seconds.
235
     *
236
     * @param int $loop_time_in_seconds
237
     *
238
     * @return $this
239
     */
240
    public function handleGetUpdatesLoop($loop_time_in_seconds)
241
    {
242
        // Remember the time we started this loop.
243
        $now = time();
244
245
        echo 'Looping getUpdates until ' . date('Y-m-d H:i:s', $now + $loop_time_in_seconds) . PHP_EOL;
246
247
        while ($now > time() - $loop_time_in_seconds) {
248
            $this->handleGetUpdates();
249
250
            // Chill a bit.
251
            sleep(2);
252
        }
253
254
        return $this;
255
    }
256
257
    /**
258
     * Handle the updates using the getUpdates method.
259
     */
260
    public function handleGetUpdates()
261
    {
262
        echo date('Y-m-d H:i:s', time()) . ' - ';
263
264
        $response = $this->telegram->handleGetUpdates();
265
        if ($response->isOk()) {
266
            $results = array_filter((array)$response->getResult());
267
268
            printf('Updates processed: %d' . PHP_EOL, count($results));
269
270
            /** @var Entities\Update $result */
271
            foreach ($results as $result) {
272
                $chat_id = 0;
273
                $text    = 'Nothing';
274
275
                $update_content = $result->getUpdateContent();
276
                if ($update_content instanceof Entities\Message) {
277
                    $chat_id = $update_content->getFrom()->getId();
278
                    $text    = $update_content->getText();
279
                } elseif ($update_content instanceof Entities\InlineQuery || $update_content instanceof Entities\ChosenInlineResult) {
280
                    $chat_id = $update_content->getFrom()->getId();
281
                    $text    = $update_content->getQuery();
282
                }
283
284
                printf(
285
                    '%d: %s' . PHP_EOL,
286
                    $chat_id,
287
                    preg_replace('/\s+/', ' ', trim($text))
288
                );
289
            }
290
        } else {
291
            printf('Failed to fetch updates: %s' . PHP_EOL, $response->printError());
292
        }
293
294
        return $this;
295
    }
296
297
    /**
298
     * Handle the updates using the Webhook method.
299
     *
300
     * @throws \InvalidArgumentException
301
     */
302
    public function handleWebhook()
303
    {
304
        $this->telegram->handle();
305
306
        return $this;
307
    }
308
}
309