Passed
Push — dev ( 865032...353ead )
by Mattia
03:59
created

MojangClient::setData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Minecraft;
6
7
use GuzzleHttp;
8
9
/**
10
 * Class MojangClient.
11
 */
12
class MojangClient
13
{
14
    /**
15
     * User Agent used for requests.
16
     */
17
    private const USER_AGENT = 'Minepic 2.0 (minepic.org)';
18
19
    /**
20
     * HTTP Client for requests.
21
     *
22
     * @var GuzzleHttp\Client
23
     */
24
    private $httpClient;
25
26
    /**
27
     * Method for Guzzle.
28
     *
29
     * @var string
30
     */
31
    private $method = 'GET';
32
33
    /**
34
     * URL for Guzzle.
35
     *
36
     * @var string
37
     */
38
    private $url = '';
39
40
    /**
41
     * Data array for Guzzle.
42
     *
43
     * @var array
44
     */
45
    private $data = [];
46
47
    /**
48
     * Last API Response.
49
     *
50
     * @var
51
     */
52
    private $lastResponse;
53
54
    /**
55
     * Last Error.
56
     *
57
     * @var string
58
     */
59
    private $lastError = '';
60
61
    /**
62
     * Last error code.
63
     *
64
     * @var int
65
     */
66
    private $lastErrorCode = 0;
67
68
    /**
69
     * Last content Type.
70
     *
71
     * @var string
72
     */
73
    private $lastContentType = '';
74
75
    /**
76
     * MojangClient constructor.
77
     */
78
    public function __construct()
79
    {
80
        $this->httpClient = new GuzzleHttp\Client(
81
            [
82
                'headers' => [
83
                    'User-Agent' => self::USER_AGENT,
84
                ],
85
            ]
86
        );
87
    }
88
89
    /**
90
     * Set HTTP Method.
91
     *
92
     * @param string $method
93
     */
94
    private function setMethod($method = '')
95
    {
96
        $this->method = $method;
97
    }
98
99
    /**
100
     * Set URL.
101
     *
102
     * @param string $url
103
     */
104
    private function setURL($url = '')
105
    {
106
        $this->url = $url;
107
    }
108
109
    /**
110
     * Last response from API.
111
     *
112
     * @return mixed
113
     */
114
    public function getLastResponse()
115
    {
116
        return $this->lastResponse;
117
    }
118
119
    private function handleGuzzleBadResponseException(
120
        GuzzleHttp\Exception\BadResponseException $badResponseException
121
    ): void {
122
        $this->lastContentType = $badResponseException->getResponse()->getHeader('content-type')[0] ?? '';
123
        $this->lastErrorCode = $badResponseException->getResponse()->getStatusCode();
124
        $this->lastError = 'Error';
125
        if (isset($this->lastResponse['errorMessage'])) {
126
            $this->lastError .= ': '.$this->lastResponse['errorMessage'];
127
        }
128
    }
129
130
    private function handleThrowable(\Throwable $exception): void
131
    {
132
        $this->lastContentType = '';
133
        $this->lastErrorCode = 0;
134
        $this->lastError = $exception->getFile().':'.$exception->getLine().' - '.$exception->getMessage();
135
    }
136
137
    /**
138
     * Send new request.
139
     */
140
    private function sendRequestApi(): bool
141
    {
142
        try {
143
            $response = $this->httpClient->request($this->method, $this->url, $this->data);
144
            $this->lastResponse = GuzzleHttp\json_decode($response->getBody()->getContents(), true);
145
            $this->lastContentType = $response->getHeader('content-type')[0];
146
            $this->lastErrorCode = 0;
147
            $this->lastError = '';
148
149
            return true;
150
        } catch (GuzzleHttp\Exception\BadResponseException $exception) {
151
            $this->lastResponse = GuzzleHttp\json_decode($exception->getResponse()->getBody()->getContents(), true);
152
            $this->handleGuzzleBadResponseException($exception);
153
154
            return false;
155
        } catch (\Throwable $exception) {
156
            $this->handleThrowable($exception);
157
158
            return false;
159
        }
160
    }
161
162
    /**
163
     * Generic request.
164
     */
165
    private function sendRequest(): bool
166
    {
167
        try {
168
            $response = $this->httpClient->request($this->method, $this->url, $this->data);
169
            $this->lastResponse = $response->getBody()->getContents();
170
            $this->lastContentType = $response->getHeader('content-type')[0];
171
            $this->lastErrorCode = 0;
172
            $this->lastError = '';
173
174
            return true;
175
        } catch (GuzzleHttp\Exception\BadResponseException $exception) {
176
            $this->lastResponse = $exception->getResponse()->getBody()->getContents();
177
            $this->handleGuzzleBadResponseException($exception);
178
179
            return false;
180
        } catch (\Throwable $exception) {
181
            $this->handleThrowable($exception);
182
183
            return false;
184
        }
185
    }
186
187
    /**
188
     * Account info from username.
189
     *
190
     * @param string $username
191
     * @return MojangAccount
192
     * @throws \Exception
193
     */
194
    public function sendUsernameInfoRequest(string $username): MojangAccount
195
    {
196
        $this->setMethod('GET');
197
        $this->setURL(env('MINECRAFT_PROFILE_URL').$username);
198
        if ($this->sendRequestApi()) {
199
            return new MojangAccount([
200
                'username' => $this->lastResponse['name'],
201
                'uuid' => $this->lastResponse['id'],
202
            ]);
203
        }
204
        throw new \Exception($this->lastError, $this->lastErrorCode);
205
    }
206
207
    /**
208
     * Account info from UUID.
209
     *
210
     * @throws \Exception
211
     */
212
    public function getUuidInfo(string $uuid): MojangAccount
213
    {
214
        $this->setMethod('GET');
215
        $this->setURL(env('MINECRAFT_SESSION_URL').$uuid);
216
        if ($this->sendRequestApi()) {
217
            $account = new MojangAccount();
218
            if ($account->loadFromApiResponse($this->lastResponse)) {
219
                return $account;
220
            }
221
            throw new \Exception('Cannot create data account');
222
        }
223
        throw new \Exception($this->lastError, $this->lastErrorCode);
224
    }
225
226
    /**
227
     * Get Skin.
228
     *
229
     * @param string $skin
230
     * @throws \Exception
231
     */
232
    public function getSkin(string $skin)
233
    {
234
        $this->setMethod('GET');
235
        $this->setURL(env('MINECRAFT_TEXTURE_URL').$skin);
236
        if ($this->sendRequest()) {
237
            if ($this->lastContentType === 'image/png') {
238
                return $this->lastResponse;
239
            }
240
            throw new \Exception('Invalid format: ');
241
        }
242
        throw new \Exception($this->lastError, $this->lastErrorCode);
243
    }
244
}
245