Completed
Branch develop (9cf893)
by Armando
02:30
created

BotManager::getOutput()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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