MessageUtility   A
last analyzed

Complexity

Total Complexity 26

Size/Duplication

Total Lines 210
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 6

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 26
lcom 2
cbo 6
dl 0
loc 210
ccs 56
cts 56
cp 1
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A removeMentionedBot() 0 6 1
A isBotMentioned() 0 6 1
A extractCommandName() 0 18 2
A extractCommandDetails() 0 8 1
A removeTriggerWord() 0 6 1
A linkToUser() 0 12 3
A getUserLink() 0 4 1
A keywordPos() 0 18 5
A keywordCount() 0 14 3
A isPositionTaken() 0 15 4
A isPositionIn() 0 10 4
1
<?php
2
3
namespace Botonomous\utility;
4
5
use Botonomous\BotonomousException;
6
use Botonomous\CommandContainer;
7
8
/**
9
 * Class MessageUtility.
10
 */
11
class MessageUtility extends AbstractUtility
12
{
13
    /**
14
     * Remove the mentioned bot username from the message.
15
     *
16
     * @param $message
17
     *
18
     * @throws \Exception
19
     *
20
     * @return string
21
     */
22 10
    public function removeMentionedBot(string $message): string
23
    {
24 10
        $userLink = $this->getUserLink();
25
26 10
        return preg_replace("/{$userLink}/", '', $message, 1);
27
    }
28
29
    /**
30
     * Check if the bot user id is mentioned in the message.
31
     *
32
     * @param $message
33
     *
34
     * @throws \Exception
35
     *
36
     * @return bool
37
     */
38 2
    public function isBotMentioned(string $message): bool
39
    {
40 2
        $userLink = $this->getUserLink();
41
42 2
        return (new StringUtility())->findInString($userLink, $message, false);
43
    }
44
45
    /**
46
     * Return command name in the message.
47
     *
48
     * @param string $message
49
     *
50
     * @throws \Exception
51
     *
52
     * @return null|string
53
     */
54 9
    public function extractCommandName(string $message)
55
    {
56
        // remove the bot mention if it exists
57 9
        $message = $this->removeMentionedBot($message);
58
59
        /**
60
         * Command must start with / and at the beginning of the sentence.
61
         */
62 9
        $commandPrefix = $this->getConfig()->get('commandPrefix');
63 9
        $commandPrefix = preg_quote($commandPrefix, '/');
64
65 9
        $pattern = '/^('.$commandPrefix.'\w{1,})/';
66
67 9
        preg_match($pattern, ltrim($message), $groups);
68
69
        // If command is found, remove command prefix from the beginning of the command
70 9
        return isset($groups[1]) ? ltrim($groups[1], $commandPrefix) : null;
71
    }
72
73
    /**
74
     * Return command details in the message.
75
     *
76
     * @param string $message
77
     *
78
     * @throws \Exception
79
     *
80
     * @return \Botonomous\Command|null
81
     */
82 1
    public function extractCommandDetails(string $message)
83
    {
84
        // first get the command name
85 1
        $command = $this->extractCommandName($message);
86
87
        // then get the command details
88 1
        return (new CommandContainer())->getAsObject($command);
89
    }
90
91
    /**
92
     * @param $triggerWord
93
     * @param $message
94
     *
95
     * @return string
96
     */
97 4
    public function removeTriggerWord(string $message, string $triggerWord)
98
    {
99 4
        $count = 1;
100
101 4
        return ltrim(str_replace($triggerWord, '', $message, $count));
102
    }
103
104
    /**
105
     * @param        $userId
106
     * @param string $userName
107
     *
108
     * @throws \Exception
109
     *
110
     * @return string
111
     */
112 13
    public function linkToUser(string $userId, string $userName = '')
113
    {
114 13
        if (empty($userId)) {
115 1
            throw new BotonomousException('User id is not provided');
116
        }
117
118 13
        if (!empty($userName)) {
119 1
            $userName = "|{$userName}";
120
        }
121
122 13
        return "<@{$userId}{$userName}>";
123
    }
124
125
    /**
126
     * @throws \Exception
127
     *
128
     * @return string
129
     */
130 12
    private function getUserLink(): string
131
    {
132 12
        return $this->linkToUser($this->getConfig()->get('botUserId'));
133
    }
134
135
    /**
136
     * @param array $keywords
137
     * @param       $message
138
     *
139
     * @return array
140
     */
141 6
    public function keywordPos(array $keywords, string $message): array
142
    {
143 6
        $found = [];
144 6
        if (empty($keywords)) {
145 2
            return $found;
146
        }
147
148 6
        foreach ((new ArrayUtility())->sortArrayByLength($keywords) as $keyword) {
149 6
            foreach ((new StringUtility())->findPositionInString($keyword, $message) as $position) {
150
                // check if the keyword does not overlap with one of the already found
151 4
                if ($this->isPositionTaken($found, $position) === false) {
152 6
                    $found[$keyword][] = $position;
153
                }
154
            }
155
        }
156
157 6
        return $found;
158
    }
159
160
    /**
161
     * @param array $keywords
162
     * @param       $message
163
     *
164
     * @return array|void
165
     */
166 5
    public function keywordCount(array $keywords, string $message)
167
    {
168 5
        $keysPositions = $this->keywordPos($keywords, $message);
169
170 5
        if (empty($keysPositions)) {
171 4
            return;
172
        }
173
174 3
        foreach ($keysPositions as $key => $positions) {
175 3
            $keysPositions[$key] = count($positions);
176
        }
177
178 3
        return $keysPositions;
179
    }
180
181
    /**
182
     * @param array $tokensPositions
183
     * @param       $newPosition
184
     *
185
     * @return bool
186
     */
187 4
    private function isPositionTaken(array $tokensPositions, int $newPosition)
188
    {
189 4
        if (empty($tokensPositions)) {
190 4
            return false;
191
        }
192
193 4
        foreach ($tokensPositions as $token => $positions) {
194 4
            $tokenLength = strlen($token);
195 4
            if ($this->isPositionIn($newPosition, $positions, $tokenLength) === true) {
196 4
                return true;
197
            }
198
        }
199
200 4
        return false;
201
    }
202
203
    /**
204
     * @param $newPosition
205
     * @param $positions
206
     * @param $tokenLength
207
     *
208
     * @return bool
209
     */
210 4
    private function isPositionIn(int $newPosition, array $positions, int $tokenLength)
211
    {
212 4
        foreach ($positions as $position) {
213 4
            if ($newPosition >= $position && $newPosition < $position + $tokenLength) {
214 4
                return true;
215
            }
216
        }
217
218 4
        return false;
219
    }
220
}
221