This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | namespace Sovereign; |
||
3 | |||
4 | |||
5 | use Discord\Cache\Cache; |
||
6 | use Discord\Cache\Drivers\ArrayCacheDriver; |
||
7 | use Discord\Discord; |
||
8 | use Discord\Parts\Channel\Message; |
||
9 | use Discord\Parts\Guild\Guild; |
||
10 | use Discord\Parts\User\Game; |
||
11 | use Discord\Parts\WebSockets\PresenceUpdate; |
||
12 | use Discord\WebSockets\Event; |
||
13 | use Discord\WebSockets\WebSocket; |
||
14 | use Monolog\Logger; |
||
15 | use League\Container\Container; |
||
16 | use Sovereign\Lib\Config as globalConfig; |
||
17 | use Sovereign\Lib\cURL; |
||
18 | use Sovereign\Lib\Db; |
||
19 | use Sovereign\Lib\Permissions; |
||
20 | use Sovereign\Lib\Settings; |
||
21 | use Sovereign\Lib\Users; |
||
22 | use Sovereign\Plugins\onMessage\cleverBotMessage; |
||
23 | |||
24 | /** |
||
25 | * Class Sovereign |
||
26 | * @package Sovereign |
||
27 | */ |
||
28 | class Sovereign |
||
29 | { |
||
30 | /** |
||
31 | * @var WebSocket |
||
32 | */ |
||
33 | public $websocket; |
||
34 | /** |
||
35 | * @var Discord |
||
36 | */ |
||
37 | protected $discord; |
||
38 | /** |
||
39 | * @var Container |
||
40 | */ |
||
41 | protected $container; |
||
42 | /** |
||
43 | * @var Logger |
||
44 | */ |
||
45 | protected $log; |
||
46 | /** |
||
47 | * @var globalConfig |
||
48 | */ |
||
49 | protected $globalConfig; |
||
50 | /** |
||
51 | * @var Db |
||
52 | */ |
||
53 | protected $db; |
||
54 | /** |
||
55 | * @var cURL |
||
56 | */ |
||
57 | protected $curl; |
||
58 | /** |
||
59 | * @var Settings |
||
60 | */ |
||
61 | protected $settings; |
||
62 | /** |
||
63 | * @var Permissions |
||
64 | */ |
||
65 | protected $permissions; |
||
66 | /** |
||
67 | * @var Users |
||
68 | */ |
||
69 | protected $users; |
||
70 | /** |
||
71 | * @var array |
||
72 | */ |
||
73 | private $onMessage = []; |
||
74 | /** |
||
75 | * @var array |
||
76 | */ |
||
77 | private $onVoice = []; |
||
78 | /** |
||
79 | * @var array |
||
80 | */ |
||
81 | private $onTimer = []; |
||
82 | /** |
||
83 | * @var \Pool |
||
84 | */ |
||
85 | private $pool; |
||
86 | /** |
||
87 | * @var \Pool |
||
88 | */ |
||
89 | private $timers; |
||
90 | /** |
||
91 | * @var array |
||
92 | */ |
||
93 | private $audioStreams; |
||
94 | /** |
||
95 | * @var array |
||
96 | */ |
||
97 | private $extras = []; |
||
98 | |||
99 | /** |
||
100 | * Sovereign constructor. |
||
101 | * @param Container $container |
||
102 | */ |
||
103 | public function __construct(Container $container) |
||
104 | { |
||
105 | $this->container = $container; |
||
106 | $this->log = $container->get('log'); |
||
107 | $this->globalConfig = $container->get('config'); |
||
108 | $this->db = $container->get('db'); |
||
109 | $this->curl = $container->get('curl'); |
||
110 | $this->settings = $container->get('settings'); |
||
111 | $this->permissions = $container->get('permissions'); |
||
112 | $this->users = $container->get('users'); |
||
113 | $this->extras['startTime'] = time(); |
||
114 | $this->extras['memberCount'] = 0; |
||
115 | $this->extras['guildCount'] = 0; |
||
116 | $this->pool = new \Pool(count($this->onMessage), \Worker::class); |
||
117 | $this->timers = new \Pool(count($this->onTimer), \Worker::class); |
||
118 | |||
119 | // Init Discord and Websocket |
||
120 | $this->log->addInfo('Initializing Discord and Websocket connections..'); |
||
121 | $this->discord = Discord::createWithBotToken($this->globalConfig->get('token', 'bot')); |
||
122 | Cache::setCache(new ArrayCacheDriver()); |
||
123 | $this->websocket = new WebSocket($this->discord); |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * @param $type |
||
128 | * @param $command |
||
129 | * @param $class |
||
130 | * @param $perms |
||
131 | * @param $description |
||
132 | * @param $usage |
||
133 | * @param $timer |
||
134 | */ |
||
135 | public function addPlugin($type, $command, $class, $perms, $description, $usage, $timer) |
||
136 | { |
||
137 | $this->log->addInfo("Adding plugin: {$command}"); |
||
138 | $this->$type[$command] = [ |
||
139 | 'permissions' => $perms, |
||
140 | 'class' => $class, |
||
141 | 'description' => $description, |
||
142 | 'usage' => $usage, |
||
143 | 'timer' => $timer |
||
144 | ]; |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * |
||
149 | */ |
||
150 | public function run() |
||
151 | { |
||
152 | // Reap the threads! |
||
153 | $this->websocket->loop->addPeriodicTimer(600, function () { |
||
0 ignored issues
–
show
|
|||
154 | $this->log->addInfo('Restarting the threading pool, to clear out old threads..'); |
||
155 | |||
156 | // Shutdown the pool |
||
157 | $this->pool->shutdown(); |
||
158 | $this->timers->shutdown(); |
||
159 | |||
160 | // Startup the pool again |
||
161 | $this->pool = new \Pool(count($this->onMessage), \Worker::class); |
||
162 | $this->timers = new \Pool(count($this->onTimer), \Worker::class); |
||
163 | }); |
||
164 | |||
165 | // Handle the onReady event, and setup some timers and so forth |
||
166 | $this->websocket->on('ready', function (Discord $discord) { |
||
167 | $this->log->addInfo('Websocket connected..'); |
||
168 | |||
169 | // Update our presence status |
||
170 | $game = new Game(array('name' => $this->globalConfig->get('presence', 'bot', "table flippin'"), 'url' => null, 'type' => null), true); |
||
171 | $this->websocket->updatePresence($game, false); |
||
172 | |||
173 | // Count the amount of people we are available to.. |
||
174 | /** @var Guild $guild */ |
||
175 | View Code Duplication | foreach ($this->discord->getClient()->getGuildsAttribute()->all() as $guild) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
176 | $this->extras['memberCount'] += $guild->member_count; |
||
177 | $this->extras['guildCount']++; |
||
178 | $this->extras['guild']['memberCount']["id{$guild->id}"] = $guild->member_count; |
||
179 | $this->extras['onMessagePlugins'] = $this->onMessage; |
||
180 | $this->extras['onVoicePlugins'] = $this->onVoice; |
||
181 | } |
||
182 | |||
183 | $this->log->addInfo("Member count, currently available to: {$this->extras['memberCount']} people"); |
||
184 | |||
185 | // Setup the timers for the timer plugins |
||
186 | foreach ($this->onTimer as $command => $data) { |
||
187 | $this->websocket->loop->addPeriodicTimer($data['timer'], function () use ($data, $discord) { |
||
0 ignored issues
–
show
The method
addPeriodicTimer() does not seem to exist on object<React\EventLoop\Factory> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||
188 | try { |
||
189 | $plugin = new $data['class']($discord, $this->log, $this->globalConfig, $this->db, $this->curl, $this->settings, $this->permissions, $this->container->get('serverConfig'), $this->users, $this->extras); |
||
190 | $this->timers->submit($plugin); |
||
191 | } catch (\Exception $e) { |
||
192 | $this->log->addError("Error running the periodic timer: {$e->getMessage()}"); |
||
193 | } |
||
194 | }); |
||
195 | } |
||
196 | |||
197 | // Issue periodically recounting and other things (Needed because of pthreads not putting the entire context into children - leading to some weirdness in some plugins) |
||
198 | $this->websocket->loop->addPeriodicTimer(600, function () { |
||
0 ignored issues
–
show
The method
addPeriodicTimer() does not seem to exist on object<React\EventLoop\Factory> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||
199 | $this->extras['memberCount'] = 0; |
||
200 | $this->extras['guildCount'] = 0; |
||
201 | /** @var Guild $guild */ |
||
202 | View Code Duplication | foreach ($this->discord->getClient()->getGuildsAttribute()->all() as $guild) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
203 | $this->extras['memberCount'] += $guild->member_count; |
||
204 | $this->extras['guildCount']++; |
||
205 | $this->extras['guild']['memberCount']["id{$guild->id}"] = $guild->member_count; |
||
206 | $this->extras['onMessagePlugins'] = $this->onMessage; |
||
207 | $this->extras['onVoicePlugins'] = $this->onVoice; |
||
208 | } |
||
209 | |||
210 | // Output periodic information while doing the recounting stuff |
||
211 | $this->log->addInfo('Currently running audio streams: ' . count($this->audioStreams)); |
||
212 | $this->log->addInfo("Member recount, currently available to: {$this->extras['memberCount']} people"); |
||
213 | }); |
||
214 | |||
215 | // @todo run a timer to check if there are any active voice sessions - and if there are, if there are any people in those voice sessions |
||
216 | // If not, stop the session and leave the channel (To save some bandwidth) |
||
217 | }); |
||
218 | |||
219 | $this->websocket->on('error', function ($error, $websocket) { |
||
0 ignored issues
–
show
|
|||
220 | $this->log->addError('An error occurred on the websocket', [$error->getMessage()]); |
||
221 | die(1); |
||
222 | }); |
||
223 | |||
224 | $this->websocket->on('close', function ($opCode, $reason) { |
||
225 | $this->log->addWarning('Websocket got closed', ['code' => $opCode, 'reason' => $reason]); |
||
226 | die(1); |
||
227 | }); |
||
228 | |||
229 | $this->websocket->on('reconnecting', function () { |
||
230 | $this->log->addInfo('Websocket is reconnecting..'); |
||
231 | }); |
||
232 | |||
233 | $this->websocket->on('reconnected', function () { |
||
234 | $this->log->addInfo('Websocket was reconnected..'); |
||
235 | }); |
||
236 | |||
237 | // Handle incoming message logging |
||
238 | $this->websocket->on(Event::MESSAGE_CREATE, function (Message $message, Discord $discord) { |
||
239 | $this->log->addInfo("Message from {$message->author->username}", [$message->content]); |
||
240 | |||
241 | // Don't update data for ourselves.. |
||
242 | if ($message->author->id !== $discord->getClient()->id) { |
||
243 | $this->users->set($message->author->id, $message->author->username, 'online', null, date('Y-m-d H:i:s'), date('Y-m-d H:i:s'), $message->content); |
||
244 | } |
||
245 | |||
246 | // @todo Create text logs |
||
247 | }); |
||
248 | |||
249 | // Handle plugin running |
||
250 | $this->websocket->on(Event::MESSAGE_CREATE, function (Message $message, Discord $discord) { |
||
251 | $guildID = $message->getChannelAttribute()->guild_id; |
||
252 | |||
253 | // Get server config |
||
254 | $config = $this->settings->get($guildID); |
||
255 | |||
256 | // Is the person admin? |
||
257 | $userDiscordID = $message->author->id; |
||
258 | foreach ($this->globalConfig->get('admins', 'permissions') as $admins) { |
||
0 ignored issues
–
show
The expression
$this->globalConfig->get('admins', 'permissions') of type null|string is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() |
|||
259 | $message->isAdmin = $admins === $userDiscordID; |
||
260 | } |
||
261 | |||
262 | // Define the prefix if it isn't already set.. |
||
263 | @$config->prefix = $config->prefix ?? $this->globalConfig->get('prefix', 'bot'); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
264 | |||
265 | // Check if the user requested an onMessage plugin |
||
266 | if (substr($message->content, 0, strlen($config->prefix)) === $config->prefix) { |
||
267 | $content = explode(' ', $message->content); |
||
268 | foreach ($this->onMessage as $command => $data) { |
||
269 | $parts = []; |
||
270 | foreach ($content as $index => $c) |
||
271 | foreach (explode("\n", $c) as $p) |
||
272 | $parts[] = $p; |
||
273 | |||
274 | if ($parts[0] === $config->prefix . $command) { |
||
275 | // If they are listed under the admins array in the bot config, they're the super admins |
||
276 | if (in_array($message->author->id, $this->globalConfig->get('admins', 'permissions'))) |
||
277 | $userPerms = 3; |
||
278 | // If they are guild owner, they're automatically getting permission level 2 |
||
279 | elseif (null !== $message->getChannelAttribute()->getGuildAttribute()->owner_id && ($message->author->id === $message->getChannelAttribute()->getGuildAttribute()->owner_id)) |
||
280 | $userPerms = 2; |
||
281 | // Everyone else are just users |
||
282 | else |
||
283 | $userPerms = 1; |
||
284 | |||
285 | if ($userPerms >= $data['permissions']) { |
||
286 | try { |
||
287 | $message->getChannelAttribute()->broadcastTyping(); |
||
288 | if ($data['class'] === "\\Sovereign\\Plugins\\onMessage\\auth") { |
||
289 | /** @var \Threaded $plugin */ |
||
290 | $plugin = new $data['class']($message, $discord, $config, $this->log, $this->globalConfig, $this->db, $this->curl, $this->settings, $this->permissions, $this->container->get('serverConfig'), $this->users, $this->extras); |
||
291 | $plugin->run(); |
||
292 | } else { |
||
293 | /** @var \Threaded $plugin */ |
||
294 | $plugin = new $data['class']($message, $discord, $config, $this->log, $this->globalConfig, $this->db, $this->curl, $this->settings, $this->permissions, $this->container->get('serverConfig'), $this->users, $this->extras); |
||
295 | $this->pool->submit($plugin); |
||
296 | } |
||
297 | $this->log->addInfo("{$message->author->username}#{$message->author->discriminator} ({$message->author}) ran command {$config->prefix}{$command}", $content); |
||
298 | } catch (\Exception $e) { |
||
299 | $this->log->addError("Error running command {$config->prefix}{$command}. Command run by {$message->author->username} in {$message->getChannelAttribute()->name}. Error: {$e->getMessage()}"); |
||
300 | $message->reply("**Error:** There was a problem running the command: {$e->getMessage()}"); |
||
301 | } |
||
302 | } |
||
303 | } |
||
304 | } |
||
305 | } |
||
306 | }); |
||
307 | |||
308 | // Handle joining a voice channel, and playing.. stuff.... |
||
309 | $this->websocket->on(Event::MESSAGE_CREATE, function (Message $message, Discord $discord) { |
||
310 | // Get the guildID |
||
311 | $guildID = $message->getChannelAttribute()->guild_id; |
||
312 | |||
313 | // Get this guilds settings |
||
314 | $config = $this->settings->get($guildID); |
||
315 | |||
316 | // Get the prefix for this guild |
||
317 | @$config->prefix = $config->prefix ?? $this->globalConfig->get('prefix', 'bot'); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
318 | |||
319 | if (substr($message->content, 0, strlen($config->prefix)) === $config->prefix) { |
||
320 | $content = explode(' ', $message->content); |
||
321 | foreach ($this->onVoice as $command => $data) { |
||
322 | $parts = []; |
||
323 | foreach ($content as $index => $c) { |
||
324 | foreach (explode("\n", $c) as $p) |
||
325 | $parts[] = $p; |
||
326 | } |
||
327 | |||
328 | if ($parts[0] === $config->prefix . $command) { |
||
329 | try { |
||
330 | $voiceChannels = $message->getFullChannelAttribute()->getGuildAttribute()->channels->getAll('type', 'voice'); |
||
331 | foreach ($voiceChannels as $channel) { |
||
332 | if (!empty($channel->members[$message->author->id])) { |
||
333 | $voice = new $data['class'](); |
||
334 | $voice->run($message, $discord, $this->websocket, $this->log, $this->audioStreams, $channel, $this->curl); |
||
335 | } |
||
336 | } |
||
337 | } catch (\Exception $e) { |
||
338 | $this->log->addError("Error running voice command {$config->prefix}{$command}. Command run by {$message->author->username} in {$message->getChannelAttribute()->name}. Error: {$e->getMessage()}"); |
||
339 | $message->reply("**Error:** There was a problem running the command: {$e->getMessage()}"); |
||
340 | } |
||
341 | } |
||
342 | } |
||
343 | } |
||
344 | }); |
||
345 | |||
346 | // Handle if it's a message for the bot (CleverBot invocation) |
||
347 | $this->websocket->on(Event::MESSAGE_CREATE, function (Message $message, Discord $discord) { |
||
348 | // If we got highlighted we should probably answer back |
||
349 | if (stristr($message->content, $discord->getClient()->id)) { |
||
350 | try { |
||
351 | $this->pool->submit(new cleverBotMessage($message, $discord, $this->log, $this->globalConfig, $this->db, $this->curl, $this->settings, $this->permissions, $this->container->get('serverConfig'), $this->users)); |
||
352 | } catch (\Exception $e) { |
||
353 | $message->reply("**Error:** There was an error with CleverBot: {$e->getMessage()}"); |
||
354 | } |
||
355 | } |
||
356 | }); |
||
357 | |||
358 | // Handle presence updates |
||
359 | $this->websocket->on(Event::PRESENCE_UPDATE, function (PresenceUpdate $presenceUpdate) { |
||
360 | if ($presenceUpdate->user->id && $presenceUpdate->user->username) { |
||
361 | try { |
||
362 | $this->log->addInfo("Updating presence info for {$presenceUpdate->user->username}"); |
||
363 | $game = $presenceUpdate->getGameAttribute()->name ?? null; |
||
364 | $this->users->set($presenceUpdate->user->id, $presenceUpdate->user->username, $presenceUpdate->status, $game, date('Y-m-d H:i:s'), null, null); |
||
365 | } catch (\Exception $e) { |
||
366 | $this->log->addError("Error: {$e->getMessage()}"); |
||
367 | } |
||
368 | } |
||
369 | }); |
||
370 | |||
371 | // Create a new cleverbot \nick\ for this new guild |
||
372 | $this->websocket->on(Event::GUILD_CREATE, function (Guild $guild) { |
||
373 | $cleverBotExists = $this->db->queryField("SELECT serverID FROM cleverbot WHERE serverID = :serverID", "serverID", array(":serverID" => $guild->id)); |
||
374 | $guildExists = $this->db->queryField("SELECT guildID FROM guilds WHERE guildID = :serverID", "guildID", array(":serverID" => $guild->id)); |
||
375 | |||
376 | // Only create a new server nick if the cleverbot instance doesn't exist.. (Hopefully cleverbot.io is done deleting them at random) |
||
377 | if(!isset($cleverBotExists)) { |
||
378 | $this->log->addInfo("Setting up Cleverbot for {$guild->name}"); |
||
379 | $serverID = $guild->id; |
||
380 | $result = $this->curl->post('https://cleverbot.io/1.0/create', ['user' => $this->globalConfig->get('user', 'cleverbot'), 'key' => $this->globalConfig->get('key', 'cleverbot')]); |
||
381 | |||
382 | if ($result) { |
||
383 | $result = @json_decode($result); |
||
384 | $nick = $result->nick ?? false; |
||
385 | |||
386 | if ($nick) { |
||
387 | $this->db->execute('INSERT INTO cleverbot (serverID, nick) VALUES (:serverID, :nick) ON DUPLICATE KEY UPDATE nick = :nick', [':serverID' => $serverID, ':nick' => $nick]); |
||
388 | } |
||
389 | } |
||
390 | } |
||
391 | |||
392 | if(!isset($guildExists)) { |
||
393 | $this->db->execute("INSERT IGNORE INTO guilds (guildID) VALUES (:guildID)", array(":guildID" => $guild->id)); |
||
394 | |||
395 | // Send a hello message to the channel (Only if it's new!) |
||
396 | //$message = "Hello, i was invited here by someone with admin permissions, i have quite a few features that you can discover by doing %help\n"; |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
50% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
397 | //$message .= "I am sorry if i am triggering other bots aswell, you can change my trigger with %config setTrigger newTrigger (Example: %config setTrigger *)\n"; |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
43% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
398 | //$message .= "If you for some reason don't want me here after all, just kick me ;)"; |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
43% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
399 | // Get the first channel in the list (usually the default channel) |
||
400 | //$channel = $guild->channels->first(); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
59% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
401 | //$channel->sendMessage($message); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
86% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
402 | } |
||
403 | }); |
||
404 | |||
405 | // Run the websocket, and in turn, the bot! |
||
406 | $this->websocket->run(); |
||
407 | } |
||
408 | |||
409 | /** |
||
410 | * Get the configuration/settings container and return it upstream to the calling code. |
||
411 | * |
||
412 | * @return globalConfig |
||
413 | */ |
||
414 | public function getGlobalConfig() { |
||
415 | return $this->globalConfig; |
||
416 | } |
||
417 | } |
||
418 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.