Completed
Push — master ( 852ed1...bbf814 )
by Armando
02:56 queued 12s
created

BotManager::initLogging()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
c 4
b 0
f 1
dl 0
loc 14
rs 8.8571
cc 6
eloc 8
nc 2
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
        $simple_extras = [
209
            'admins'         => 'enableAdmins',
210
            'mysql'          => 'enableMySql',
211
            'botan_token'    => 'enableBotan',
212
            'commands_paths' => 'addCommandsPaths',
213
            'custom_input'   => 'setCustomInput',
214
            'download_path'  => 'setDownloadPath',
215
            'upload_path'    => 'setUploadPath',
216
        ];
217
        // For simple extras, just pass the single param value to the Telegram method.
218
        foreach ($simple_extras as $param_key => $method) {
219
            $param = $this->params->getBotParam($param_key);
220
            if (null !== $param) {
221
                $this->telegram->$method($param);
222
            }
223
        }
224
225
        $command_configs = $this->params->getBotParam('command_configs');
226
        if (is_array($command_configs)) {
227
            /** @var array $command_configs */
228
            foreach ($command_configs as $command => $config) {
229
                $this->telegram->setCommandConfig($command, $config);
230
            }
231
        }
232
233
        return $this;
234
    }
235
236
    /**
237
     * Handle the request, which calls either the Webhook or getUpdates method respectively.
238
     *
239
     * @throws \InvalidArgumentException
240
     */
241
    public function handleRequest()
242
    {
243
        if (empty($this->params->getBotParam('webhook'))) {
244
            if ($loop_time = $this->getLoopTime()) {
245
                $this->handleGetUpdatesLoop($loop_time);
246
            } else {
247
                $this->handleGetUpdates();
248
            }
249
        } else {
250
            $this->handleWebhook();
251
        }
252
253
        return $this;
254
    }
255
256
    /**
257
     * Get the number of seconds the script should loop.
258
     *
259
     * @return int
260
     */
261
    public function getLoopTime()
262
    {
263
        $loop_time = $this->params->getScriptParam('l');
264
265
        if (null === $loop_time) {
266
            return 0;
267
        }
268
269
        if ('' === trim($loop_time)) {
270
            return 604800; // Default to 7 days.
271
        }
272
273
        return max(0, (int)$loop_time);
274
    }
275
276
    /**
277
     * Loop the getUpdates method for the passed amount of seconds.
278
     *
279
     * @param int $loop_time_in_seconds
280
     *
281
     * @return $this
282
     */
283
    public function handleGetUpdatesLoop($loop_time_in_seconds)
284
    {
285
        // Remember the time we started this loop.
286
        $now = time();
287
288
        $this->handleOutput('Looping getUpdates until ' . date('Y-m-d H:i:s', $now + $loop_time_in_seconds) . PHP_EOL);
289
290
        while ($now > time() - $loop_time_in_seconds) {
291
            $this->handleGetUpdates();
292
293
            // Chill a bit.
294
            sleep(2);
295
        }
296
297
        return $this;
298
    }
299
300
    /**
301
     * Handle the updates using the getUpdates method.
302
     */
303
    public function handleGetUpdates()
304
    {
305
        $output = date('Y-m-d H:i:s', time()) . ' - ';
306
307
        $response = $this->telegram->handleGetUpdates();
308
        if ($response->isOk()) {
309
            $results = array_filter((array)$response->getResult());
310
311
            $output .= sprintf('Updates processed: %d' . PHP_EOL, count($results));
312
313
            /** @var Entities\Update $result */
314
            foreach ($results as $result) {
315
                $chat_id = 0;
316
                $text    = 'Nothing';
317
318
                $update_content = $result->getUpdateContent();
319
                if ($update_content instanceof Entities\Message) {
320
                    $chat_id = $update_content->getFrom()->getId();
321
                    $text    = $update_content->getText();
322
                } elseif ($update_content instanceof Entities\InlineQuery || $update_content instanceof Entities\ChosenInlineResult) {
323
                    $chat_id = $update_content->getFrom()->getId();
324
                    $text    = $update_content->getQuery();
325
                }
326
327
                $output .= sprintf(
328
                    '%d: %s' . PHP_EOL,
329
                    $chat_id,
330
                    preg_replace('/\s+/', ' ', trim($text))
331
                );
332
            }
333
        } else {
334
            $output .= sprintf('Failed to fetch updates: %s' . PHP_EOL, $response->printError());
335
        }
336
337
        $this->handleOutput($output);
338
339
        return $this;
340
    }
341
342
    /**
343
     * Handle the updates using the Webhook method.
344
     *
345
     * @throws \InvalidArgumentException
346
     */
347
    public function handleWebhook()
348
    {
349
        $this->telegram->handle();
350
351
        return $this;
352
    }
353
354
    /**
355
     * Return the current test output and clear it.
356
     *
357
     * @return string
358
     */
359
    public function getOutput()
360
    {
361
        $output       = $this->output;
362
        $this->output = '';
363
364
        return $output;
365
    }
366
}
367