Passed
Branch master (268ef2)
by
unknown
03:29
created

Dramiel.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * The MIT License (MIT)
4
 *
5
 * Copyright (c) 2016  Robert Sardinia
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in all
15
 * copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
 * SOFTWARE.
24
 */
25
26
// Require the vendor stuff
27
/** @noinspection PhpIncludeInspection */
28
require_once __DIR__ . '/vendor/autoload.php';
29
30
// Setup logger
31
use Discord\Discord;
32
use Discord\Parts\User\Game;
33
use Discord\WebSockets\Event;
34
use Discord\WebSockets\WebSocket;
35
use Monolog\Handler\StreamHandler;
36
use Monolog\Logger;
37
38
// More memory allowance
39
ini_set('memory_limit', '1024M');
40
41
// Just in case we get launched from somewhere else
42
chdir(__DIR__);
43
44
// Enable garbage collection
45
gc_enable();
46
47
// When the bot started
48
$startTime = time();
49
50
// create a log channel
51
$logger = new Logger('Dramiel');
52
$logger->pushHandler(new StreamHandler(__DIR__ . '/log/dramielLog.log', Logger::INFO));
53
$logger->addInfo('Logger Initiated');
54
55
GLOBAL $logger;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
56
57
//Check we are not running on a 32bit platform
58
if(PHP_INT_SIZE == 4)
59
{
60
	$logger->error('32bit PHP found, if you are running a 64bit OS please install 64bit PHP');
61
	die();
62
}
63
64
// Require the config
65
if (file_exists('config/config.php')) {
66
    /** @noinspection PhpIncludeInspection */
67
    require_once 'config/config.php';
68
} else {
69
    $logger->error('config.php not found (you might wanna start by editing and renaming config_new.php)');
70
    die();
71
}
72
73
// Load the library files (Probably a prettier way to do this that i haven't thought up yet)
74
foreach (glob(__DIR__ . '/src/lib/*.php') as $lib) {
75
    /** @noinspection PhpIncludeInspection */
76
    require_once $lib;
77
}
78
79
//Startup DB Check
80
updateDramielDB($logger);
81
82
// Init Discord
83
$discord = new Discord(['token' => $config['bot']['token']]);
84
85
// Load tick plugins
86
$pluginDirs = array('src/plugins/onTick/*.php');
87
$logger->info('Loading background plugins');
88
$plugins = array();
89
$pluginsT = array();
90
foreach ($pluginDirs as $dir) {
91
    foreach (glob($dir) as $plugin) {
92
        // Only load the plugins we want to load, according to the config
93
        if (!in_array(str_replace('.php', '', basename($plugin)), $config['enabledPlugins'])) {
94
            continue;
95
        }
96
97
        /** @noinspection PhpIncludeInspection */
98
        require_once $plugin;
99
        $fileName = str_replace('.php', '', basename($plugin));
100
        $p = new $fileName();
101
        $p->init($config, $discord, $logger);
102
        $pluginsT[] = $p;
103
    }
104
}
105
// Number of plugins loaded
106
$logger->info('Loaded: ' . count($pluginsT) . ' background plugins');
107
108
if ($config['bot']['silentMode'] == 'false' || !isset($config['bot']['silentMode'])) {
109
// Load chat plugins
110
    $pluginDirs = array('src/plugins/onMessage/*.php', 'src/plugins/admin/*.php');
111
    $adminPlugins = array('setNickname', 'getLog', 'setGame', 'setAvatar');
112
    $logger->addInfo('Loading in chat plugins');
113
    $plugins = array();
114
    foreach ($pluginDirs as $dir) {
115
        foreach (glob($dir) as $plugin) {
116
            // Only load the plugins we want to load, according to the config
117
            if (!in_array(str_replace('.php', '', basename($plugin)), $config['enabledPlugins']) && !in_array(str_replace('.php', '', basename($plugin)), $adminPlugins)) {
118
                continue;
119
            }
120
121
            /** @noinspection PhpIncludeInspection */
122
            require_once $plugin;
123
            $fileName = str_replace('.php', '', basename($plugin));
124
            $p = new $fileName();
125
            $p->init($config, $discord, $logger);
126
            $plugins[] = $p;
127
        }
128
    }
129
130
// Number of chat plugins loaded
131
    $logger->addInfo('Loaded: ' . count($plugins) . ' chat plugins');
132
}
133
134
// Clear queue at restart if it's too high
135
clearQueueCheck();
136
137
//Check initial server state (tick plugins will not run if eve is offline)
138
$crestData = json_decode(downloadData('https://crest-tq.eveonline.com/'), true);
139
$crestStatus = isset($crestData['serviceStatus']) ? $crestData['serviceStatus'] : 'offline';
140
setPermCache('serverState', $crestStatus);
141
setPermCache('statusLastState', $crestStatus);
142
$logger->addInfo("serverState: EVE is currently {$crestStatus}");
143
144
//Clean up any outdated databases
145
dbPrune();
146
147
$discord->on(
148
    'ready',
149
    function($discord) use ($logger, $config, $plugins, $pluginsT) {
150
        // In here we can access any of the WebSocket events.
151
        //
152
        // There is a list of event constants that you can
153
        // find here: https://teamreflex.github.io/DiscordPHP/classes/Discord.WebSockets.Event.html
154
        //
155
        // We will echo to the console that the WebSocket is ready.
156
        $logger->addInfo('Discord WebSocket is ready!' . PHP_EOL);
157
158
        //Clear queue if it's super backed up
159
160
161
        //Set Initial Game
162
        $gameTitle = $config['bot']['game'];
163
        if (null !== getPermCache('botGame')) {
164
            $gameTitle = getPermCache('botGame');
165
        }
166
        $game = $discord->factory(Game::class, [
167
            'name' => $gameTitle,
168
        ]);
169
        $discord->updatePresence($game);
170
171
        // Server Status Check (tick plugins will not run if eve is offline)
172
        $discord->loop->addPeriodicTimer(60, function() use ($logger) {
173
            $crestData = json_decode(downloadData('https://crest-tq.eveonline.com/'), true);
174
            $crestStatus = isset($crestData['serviceStatus']) ? $crestData['serviceStatus'] : 'offline';
175
            setPermCache('serverState', $crestStatus);
176
        });
177
178
        // Run the Tick plugins
179
        $discord->loop->addPeriodicTimer(3, function() use ($pluginsT) {
180
            foreach ($pluginsT as $plugin) {
181
                $plugin->tick();
182
            }
183
        });
184
185
        // Message queue
186
        $discord->loop->addPeriodicTimer(7, function() use ($discord, $logger) {
187
            $x = 0;
188
            while ($x < 3) {
189
                $id = getOldestMessage();
0 ignored issues
show
Are you sure the assignment to $id is correct as getOldestMessage() seems to always returns null.
Loading history...
190
                $id = $id['MIN(id)'];
191
                if (null === $id) {
192
                    $id = 1;
193
                }
194
                $queuedMessage = getQueuedMessage($id);
0 ignored issues
show
Are you sure the assignment to $queuedMessage is correct as getQueuedMessage($id) (which targets getQueuedMessage()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
195
                if (null !== $queuedMessage) {
196
                    //Check if queued item is corrupt and delete it if it is
197
                    if (null === $queuedMessage['guild'] || null === $queuedMessage['channel'] || null === $queuedMessage['message']) {
198
                        $logger->addInfo("QueueProcessing Error- Item #{$id} : Queued item is badly formed, removing it from the queue");
199
                        clearQueuedMessages($id);
200
                        continue;
201
                    }
202
                    $guild = $discord->guilds->get('id', $queuedMessage['guild']);
203
                    //Check if guild is bad
204
                    if (null === $guild) {
205
                        $logger->addInfo("QueueProcessing Error- Item #{$id} : Guild provided is incorrect, removing it from the queue");
206
                        clearQueuedMessages($id);
207
                        continue;
208
                    }
209
                    $channel = $guild->channels->get('id', (int)$queuedMessage['channel']);
210
                    //Check if channel is bad
211
                    if (null === $channel) {
212
                        $logger->addInfo("QueueProcessing Error- Item #{$id} : Channel provided is incorrect, removing it from the queue");
213
                        clearQueuedMessages($id);
214
                        continue;
215
                    }
216
                    $logger->addInfo("QueueProcessing - Completing queued item #{$id}");
217
                    $channel->sendMessage($queuedMessage['message'], false, null);
218
                    clearQueuedMessages($id);
219
                }
220
                $x++;
221
            }
222
        });
223
224
        // Rename queue
225
        $discord->loop->addPeriodicTimer(10, function() use ($discord, $logger) {
226
            $x = 0;
227
            while ($x < 4) {
228
                $id = getOldestRename();
0 ignored issues
show
Are you sure the assignment to $id is correct as getOldestRename() seems to always returns null.
Loading history...
229
                $id = $id['MIN(id)'];
230
                if (null === $id) {
231
                    $id = 1;
232
                    $x = 4;
233
                }
234
                $queuedRename = getQueuedRename($id);
0 ignored issues
show
Are you sure the assignment to $queuedRename is correct as getQueuedRename($id) (which targets getQueuedRename()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
235
                if (null !== $queuedRename) {
236
                    //Check if queued item is corrupt and delete it if it is
237
                    if (null === $queuedRename['guild'] || null === $queuedRename['discordID']) {
238
                        clearQueuedRename($id);
239
                    }
240
                    $guild = $discord->guilds->get('id', $queuedRename['guild']);
241
                    $member = $guild->members->get('id', $queuedRename['discordID']);
242
                    $member->setNickname($queuedRename['nick']);
243
                    clearQueuedRename($id);
244
                }
245
                $x++;
246
            }
247
        });
248
249
        // Mem cleanup every 30 minutes
250
        $discord->loop->addPeriodicTimer(1800, function() use ($logger) {
251
            $logger->addInfo('Memory in use: ' . memory_get_usage() / 1024 / 1024 . 'MB');
252
            gc_collect_cycles(); // Collect garbage
253
            $logger->addInfo('Memory in use after garbage collection: ' . memory_get_usage() / 1024 / 1024 . 'MB');
254
        });
255
256
        $discord->on(
257
            Event::MESSAGE_CREATE,
258
            function($message) use ($logger, $config, $plugins) {
259
260
                $msgData = array(
261
                    'message' => array(
262
                        'timestamp' => @$message->timestamp,
263
                        'id' => @$message->id,
264
                        'message' => @$message->content,
265
                        'channelID' => @$message->channel_id,
266
                        'from' => @$message->author->username,
267
                        'fromID' => @$message->author->id,
268
                        'fromDiscriminator' => @$message->author->discriminator,
269
                        'fromAvatar' => @$message->author->avatar
270
                    )
271
                );
272
273
                if ($message->content == '(╯°□°)╯︵ ┻━┻') {
274
                    $message->reply('┬─┬ ノ( ゜-゜ノ)');
275
                }
276
277
                // Check for plugins
278
                if (isset($message->content[0])) {
279
                    if ($message->content[0] == $config['bot']['trigger']) {
280
                        foreach ($plugins as $plugin) {
281
                            try {
282
                                $plugin->onMessage($msgData, $message);
283
                            } catch (Exception $e) {
284
                                $logger->addError('Error: ' . $e->getMessage());
285
                            }
286
                        }
287
                    }
288
                }
289
            }
290
        );
291
    }
292
);
293
$discord->on(
294
    'error',
295
    function($error) use ($logger) {
296
        $logger->addError($error);
297
        exit(1);
298
    }
299
);
300
$discord->on(
301
    'reconnecting',
302
    function() use ($logger) {
303
        $logger->addInfo('Websocket is reconnecting..');
304
    });
305
$discord->on(
306
    'reconnected',
307
    function() use ($logger) {
308
        $logger->addInfo('Websocket was reconnected..');
309
    });
310
// Now we will run the ReactPHP Event Loop!
311
$discord->run();
312
313