Completed
Push — master ( 825fd0...b0546e )
by Dan
02:02
created

Yabot   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 146
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 11
dl 0
loc 146
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 1
A getMessageLog() 0 4 1
A setMessageLog() 0 4 1
A init() 0 15 3
A run() 0 12 1
A connected() 0 10 1
B onMessage() 0 25 4
A getHelp() 0 4 1
A getStatus() 0 8 1
A addMemoryReporting() 0 14 1
A getFormattedMemoryUsage() 0 6 1
A logMessage() 0 4 1
1
<?php
2
3
namespace Nopolabs\Yabot;
4
5
use DateTime;
6
use Exception;
7
use Nopolabs\Yabot\Helpers\LogTrait;
8
use Nopolabs\Yabot\Helpers\LoopTrait;
9
use Nopolabs\Yabot\Helpers\SlackTrait;
10
use Nopolabs\Yabot\Message\MessageFactory;
11
use Nopolabs\Yabot\Plugin\PluginInterface;
12
use Nopolabs\Yabot\Plugin\PluginManager;
13
use Nopolabs\Yabot\Slack\Client;
14
use Psr\Log\LoggerInterface;
15
use React\EventLoop\LoopInterface;
16
use Slack\Payload;
17
use Slack\User;
18
use Throwable;
19
20
class Yabot
21
{
22
    use LogTrait;
23
    use LoopTrait;
24
    use SlackTrait;
25
26
    /** @var MessageFactory */
27
    private $messageFactory;
28
29
    /** @var PluginManager */
30
    private $pluginManager;
31
32
    private $messageLog;
33
34
    public function __construct(
35
        LoggerInterface $logger,
36
        LoopInterface $eventLoop,
37
        Client $slackClient,
38
        MessageFactory $messageFactory,
39
        PluginManager $pluginManager
40
    ) {
41
        $this->setLog($logger);
42
        $this->setLoop($eventLoop);
43
        $this->setSlack($slackClient);
44
        $this->messageFactory = $messageFactory;
45
        $this->pluginManager = $pluginManager;
46
        $this->messageLog = null;
47
    }
48
49
    public function getMessageLog()
50
    {
51
        return $this->messageLog;
52
    }
53
54
    public function setMessageLog(string $messageLog = null)
55
    {
56
        $this->messageLog = $messageLog ?? null;
57
    }
58
59
    public function init(array $plugins)
60
    {
61
        foreach ($plugins as $pluginId => $plugin) {
62
            /** @var PluginInterface $plugin */
63
64
            $this->info("loading $pluginId");
65
66
            try {
67
                $this->pluginManager->loadPlugin($pluginId, $plugin);
68
            } catch (Exception $e) {
69
                $this->warning("Unhandled Exception while loading $pluginId: ".$e->getMessage());
70
                $this->warning($e->getTraceAsString());
71
            }
72
        }
73
    }
74
75
    public function run()
76
    {
77
        $slack = $this->getSlack();
78
79
        $slack->init();
80
81
        $slack->connect()->then([$this, 'connected']);
82
83
        $this->addMemoryReporting();
84
85
        $this->getLoop()->run();
86
    }
87
88
    public function connected()
89
    {
90
        $slack = $this->getSlack();
91
92
        $slack->update(function(User $authedUser) {
93
            $this->pluginManager->updatePrefixes($authedUser->getUsername());
94
        });
95
96
        $slack->onEvent('message', [$this, 'onMessage']);
97
    }
98
99
    public function onMessage(Payload $payload)
100
    {
101
        $data = $payload->getData();
102
103
        $this->debug('Received message', $data);
104
105
        try {
106
            if ($this->messageLog !== null) {
107
                $this->logMessage($data);
108
            }
109
            $message = $this->messageFactory->create($data);
110
        } catch (Throwable $throwable) {
111
            $errmsg = $throwable->getMessage()."\n"
112
                .$throwable->getTraceAsString()."\n"
113
                ."Payload data: ".json_encode($data);
114
            $this->warning($errmsg);
115
            return;
116
        }
117
118
        if ($message->isSelf()) {
119
            return;
120
        }
121
122
        $this->pluginManager->dispatchMessage($message);
123
    }
124
125
    public function getHelp() : string
126
    {
127
        return implode("\n", $this->pluginManager->getHelp());
128
    }
129
130
    public function getStatus() : string
131
    {
132
        $statuses = $this->pluginManager->getStatuses();
133
134
        array_unshift($statuses, $this->getFormattedMemoryUsage());
135
136
        return implode("\n", $statuses);
137
    }
138
139
    protected function addMemoryReporting()
140
    {
141
        $now = new DateTime();
142
        $then = new DateTime('+1 hour');
143
        $then->setTime($then->format('H'), 0, 0);
144
        $delay = $then->getTimestamp() - $now->getTimestamp();
145
146
        $this->addTimer($delay, function() {
147
            $this->info($this->getFormattedMemoryUsage());
148
            $this->addPeriodicTimer(3600, function() {
149
                $this->info($this->getFormattedMemoryUsage());
150
            });
151
        });
152
    }
153
154
    protected function getFormattedMemoryUsage() : string
155
    {
156
        $memory = memory_get_usage() / 1024;
157
        $formatted = number_format($memory, 3).'K';
158
        return "Current memory usage: {$formatted}";
159
    }
160
161
    private function logMessage($data)
162
    {
163
        file_put_contents($this->messageLog, json_encode($data)."\n", FILE_APPEND);
164
    }
165
}
166