Passed
Push — develop ( d2ded6...15ac65 )
by Nikita
19:39
created

ServerService::getConsoleLog()   A

Complexity

Conditions 3
Paths 6

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.3332

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
dl 0
loc 22
ccs 8
cts 12
cp 0.6667
rs 9.8666
c 1
b 0
f 0
cc 3
nc 6
nop 1
crap 3.3332
1
<?php
2
3
namespace Gameap\Services;
4
5
use GameQ\GameQ;
6
use Gameap\Models\Server;
7
use Knik\Gameap\GdaemonCommands;
8
9
use Html;
10
use Storage;
11
use Gameap\Exceptions\Services\InvalidCommandException;
12
use Gameap\Exceptions\Services\EmptyCommandException;
13
use Gameap\Exceptions\Services\ServerInactiveException;
14
15
class ServerService
16
{
17
    const CONSOLE_MAX_SYMBOLS = 10000;
18
19
    /**
20
     * @var GameQ
21
     */
22
    protected $gameq;
23
24
    /**
25
     * @var GdaemonCommands
26
     */
27
    protected $gdaemonCommands;
28
29
    /**
30
     * @var string
31
     */
32
    protected $storageDisk = 'local';
33
34
    /**
35
     * ServerService constructor.
36
     *
37
     * @param GameQ $gameq
38
     * @param GdaemonCommands $gdaemonCommands
39
     */
40 3
    public function __construct(GameQ $gameq, GdaemonCommands $gdaemonCommands)
41
    {
42 3
        $this->gameq = $gameq;
43 3
        $this->gdaemonCommands = $gdaemonCommands;
44 3
    }
45
46
    /**
47
     * Add default server disk
48
     * 
49
     * @param Server $server
50
     */
51
    public function registerDisk(Server $server)
52
    {
53
        foreach ($server->file_manager_disks as $diskName => $diskConfig) {
54
            if (empty(config("filesystems.disks.{$diskName}"))) {
55
                config(["filesystems.disks.{$diskName}" => $diskConfig]);
56
            }
57
        }
58
    }
59
60
    /**
61
     * @param Server $server
62
     * @return array
63
     */
64 3
    public function query(Server $server)
65
    {
66 3
        $query = $this->gameq->setOption('timeout', 5)
67 3
            ->addServer([
68 3
                'type' => $server->game->engine,
69 3
                'host' => "{$server->server_ip}:{$server->query_port}",
70
            ])
71 3
            ->process();
72
73 3
        $serverResult = $query["{$server->server_ip}:{$server->query_port}"];
74
75 3
        if ($serverResult['gq_online']) {
76
            $result = [
77 3
                'status' => $serverResult['gq_online'] ? 'online' : 'offline',
78 3
                'hostname' => $serverResult['gq_hostname'],
79 3
                'map' => $serverResult['gq_mapname'],
80 3
                'players' => $serverResult['gq_numplayers'] . '/' . $serverResult['gq_maxplayers'],
81 3
                'version' => isset($serverResult['version']) ? $serverResult['version'] : null,
82 3
                'password' => $serverResult['gq_password'] ? 'yes' : 'no',
83 3
                'joinlink' => $serverResult['gq_joinlink'],
84
            ];
85
        } else {
86
            $result = [
87 3
                'status' => 'offline',
88
            ];
89
        }
90
91 3
        return $result;
92
    }
93
94
    /**
95
     * @param Server $server
96
     * @param string $command
97
     * @param array $extraData
98
     * @return string
99
     */
100 15
    public function replaceShortCodes(Server $server, string $command, array $extraData = [])
101
    {
102 15
        foreach ($extraData as $key => $value) {
103 9
            $command = str_replace('{' . $key . '}', $value, $command);
104
        }
105
106
        $replaceArray = [
107 15
            'host' => $server->server_ip,
108 15
            'port' => $server->server_port,
109 15
            'query_port' => $server->query_port,
110 15
            'rcon_port' => $server->rcon_port,
111 15
            'dir' => $server->full_path,
112 15
            'uuid' => $server->uuid,
113 15
            'uuid_short' => $server->uuid_short,
114 15
            'game' => $server->game_id,
115 15
            'user' => $server->su_user,
116
        ];
117
118 15
        foreach ($replaceArray as $key => $value) {
119 15
            $command = str_replace('{' . $key . '}', $value, $command);
120
        }
121
122 15
        return $command;
123
    }
124
125
    /**
126
     * @param Server $server
127
     * @param string $command
128
     * @param array $extraData
129
     * @return string
130
     *
131
     * @throws InvalidCommandException
132
     * @throws EmptyCommandException
133
     */
134 15
    public function getCommand(Server $server, string $command, array $extraData = [])
135
    {
136 15
        $property = 'script_' . $command;
137 15
        $attributes = $server->dedicatedServer->getAttributes();
138
139 15
        if (array_key_exists($property, $attributes)) {
140 12
            $script = $server->dedicatedServer->getAttribute($property);
141
142 12
            if (empty($script)) {
143
                throw new EmptyCommandException();
144
            }
145
146 12
            return $this->replaceShortCodes($server, $script, $extraData);
0 ignored issues
show
Bug introduced by
It seems like $script can also be of type boolean; however, parameter $command of Gameap\Services\ServerService::replaceShortCodes() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

146
            return $this->replaceShortCodes($server, /** @scrutinizer ignore-type */ $script, $extraData);
Loading history...
147
        }
148
149 3
        throw new InvalidCommandException();
150
    }
151
152
    /**
153
     * @param Server $server
154
     * @return string
155
     */
156 6
    public function getConsoleLog(Server $server)
157
    {
158 6
        $this->checkServer($server);
159 3
        $this->configureGdaemon($server);
160
161
        try {
162 3
            $command = $this->getCommand($server, 'get_console');
163 3
            $result = $this->gdaemonCommands->exec($command, $exitCode);
164
        } catch (EmptyCommandException $e) {
165
            $this->registerDisk($server);
166
            $result = Storage::disk('server')->get('output.txt');
167
        }
168
169 3
        if (mb_strlen($result) > self::CONSOLE_MAX_SYMBOLS) {
170
            $result = mb_substr($result, mb_strlen($result) - self::CONSOLE_MAX_SYMBOLS, self::CONSOLE_MAX_SYMBOLS);
171
        }
172
173
        // Fix
174
        // Malformed UTF-8 characters, possibly incorrectly encoded
175 3
        $result = mb_convert_encoding($result, 'UTF-8', 'UTF-8');
176
        
177 3
        return $result;
178
    }
179
180
    /**
181
     * @param Server $server
182
     * @param string $command
183
     * @return bool
184
     */
185 9
    public function sendConsoleCommand(Server $server, string $command)
186
    {
187 9
        $this->checkServer($server);
188 6
        $this->configureGdaemon($server);
189
190
        try {
191 6
            $command = $this->getCommand($server, 'send_command', ['command' => $command]);
192 6
            $this->gdaemonCommands->exec($command, $exitCode);
193
        } catch (EmptyCommandException $e) {
194
            $this->registerDisk($server);
195
            
196
            if (Storage::disk('server')->put('input.txt', $command)) {
197
                // Success
198
                $exitCode = 0;
199
            } else {
200
                // Failure
201
                $exitCode = 1;
202
            }
203
        }
204
205 6
        return $exitCode === 0;
206
    }
207
208
    /**
209
     * Setting up gdaemon commands configuration
210
     *
211
     * @param Server $server
212
     */
213 9
    private function configureGdaemon(Server $server)
214
    {
215 9
        $this->gdaemonCommands->setConfig(
216 9
            $server->dedicatedServer->gdaemonSettings($this->storageDisk)
217
        );
218 9
    }
219
220
    /**
221
     * @param Server $server
222
     * @throws ServerInactiveException
223
     */
224 15
    private function checkServer(Server $server)
225
    {
226 15
        if ($server->processActive() === false) {
227 6
            throw new ServerInactiveException('Server is down');
228
        }
229
    }
230
}