├── LICENSE.md ├── README.md ├── composer.json ├── data └── cacert.pem └── src ├── Profile.php └── Profile └── ApiClient.php /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Navarr Barnier 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Minecraft Profile API in PHP 2 | 3 | ## Usage 4 | 5 | Usage is super simple and well-documented. Here's a short example: 6 | 7 | ```php 8 | use Navarr\Minecraft\Profile; 9 | 10 | $profile = Profile::fromUuid('bd95beec116b4d37826c373049d3538b'); 11 | $username = $profile->name; 12 | $cape = $profile->capeUrl; 13 | $skin = $profile->skinUrl; 14 | ``` 15 | 16 | ## Installation 17 | 18 | MinecraftProfile uses Composer. For more information about composer, read the [Getting Started](https://getcomposer.org/doc/00-intro.md) document. 19 | 20 | To install with composer: 21 | 22 | > `composer install navarr/minecraft-profile` 23 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "navarr/minecraft-profile", 3 | "type": "library", 4 | "description": "Minecraft Profile API", 5 | "license": "MIT", 6 | "keywords": ["Minecraft", "Mojang"], 7 | "minimum-stability": "stable", 8 | "authors": [ 9 | { 10 | "name": "Navarr Barnier", 11 | "email": "me@navarr.me", 12 | "homepage": "http://navarr.me/", 13 | "role": "Developer" 14 | } 15 | ], 16 | "require": { 17 | "php": ">=5.5.0", 18 | "guzzlehttp/guzzle": "^6.2.1" 19 | }, 20 | "require-dev": { 21 | "phpunit/phpunit": "^3.0" 22 | }, 23 | "autoload": { 24 | "psr-4": { 25 | "Navarr\\Minecraft\\": "src/" 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Profile.php: -------------------------------------------------------------------------------- 1 | profileApi($uuid); 40 | 41 | if (is_null($json) || !isset($json->properties) || empty($json->properties) || !isset($json->properties[0]->value)) { 42 | throw new \RuntimeException('Error parsing JSON for UUID '.$uuid); 43 | } 44 | 45 | $properties = base64_decode($json->properties[0]->value); 46 | if ($properties === false) { 47 | throw new \RuntimeException('Error parsing base64 properties for UUID '.$uuid); 48 | } 49 | $properties = json_decode($properties); 50 | if (is_null($properties)) { 51 | throw new \RuntimeException('Error parsing JSON encoded properties for UUID '.$uuid); 52 | } 53 | 54 | $profile = new self(); 55 | $profile->uuid = $json->id; 56 | $profile->name = $json->name; 57 | if (isset($properties->isPublic)) { 58 | $profile->public = $properties->isPublic; 59 | } 60 | if (isset($properties->textures)) { 61 | if (isset($properties->textures->SKIN) && isset($properties->textures->SKIN->url)) { 62 | $profile->skinUrl = $properties->textures->SKIN->url; 63 | } 64 | if (isset($properties->textures->CAPE) && isset($properties->textures->CAPE->url)) { 65 | $profile->capeUrl = $properties->textures->CAPE->url; 66 | } 67 | } 68 | 69 | return $profile; 70 | } 71 | 72 | /** 73 | * For gods' sakes, use a UUID. 74 | * 75 | * @param string $username 76 | * @param Profile\ApiClient $apiClient 77 | * 78 | * @deprecated As Mojang commonly returns a 429 in response 79 | * 80 | * @throws \RuntimeException 81 | * 82 | * @return Profile 83 | */ 84 | public static function fromUsername($username, ApiClient $apiClient = null) 85 | { 86 | if (is_null($apiClient)) { 87 | $apiClient = static::createApiClient(); 88 | } 89 | 90 | $apiResult = $apiClient->uuidApi($username); 91 | 92 | $json = $apiResult; 93 | 94 | if (isset($json->error)) { 95 | throw new \RuntimeException('Mojang Error: '.$json->errorMessage); 96 | } 97 | 98 | if (empty($json) || !isset($json[0]->id)) { 99 | throw new \RuntimeException('Invalid Username ('.$username.')'); 100 | } 101 | static::rateLimitBust(); 102 | 103 | return static::fromUuid($json[0]->id); 104 | } 105 | 106 | /** 107 | * @return ApiClient 108 | */ 109 | protected static function createApiClient() 110 | { 111 | return new ApiClient(new Client()); 112 | } 113 | 114 | public function __get($var) 115 | { 116 | if (isset($this->{$var})) { 117 | return $this->{$var}; 118 | } 119 | } 120 | 121 | public function __isset($var) 122 | { 123 | return isset($this->{$var}); 124 | } 125 | 126 | private static function rateLimitBust() 127 | { 128 | sleep(1); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/Profile/ApiClient.php: -------------------------------------------------------------------------------- 1 | client = $client; 30 | } 31 | 32 | private function getOptions() 33 | { 34 | return ['verify' => __DIR__.'/../../data/cacert.pem']; 35 | } 36 | 37 | public function uuidApi($username) 38 | { 39 | $request = new Request( 40 | 'POST', 41 | static::UUID_API, 42 | ['Content-Type' => 'application/json'], 43 | json_encode([$username]) 44 | ); 45 | 46 | $response = $this->client->send($request, $this->getOptions()); 47 | $response = @json_decode($response->getBody()); 48 | 49 | if (!$response) { 50 | throw new \RuntimeException('Bad JSON from API: on username '.$username.' - '.json_last_error_msg()); 51 | } elseif (isset($response->error)) { 52 | throw new \RuntimeException('Error from API: '.$response->error.' on username '.$username); 53 | } 54 | 55 | return $response; 56 | } 57 | 58 | public function profileApi($uuid) 59 | { 60 | $request = new Request('GET', sprintf(static::PROFILE_API, $uuid)); 61 | $httpResponse = $this->client->send($request, $this->getOptions()); 62 | $response = @json_decode($httpResponse->getBody()); 63 | 64 | if ($httpResponse->getStatusCode() != 200) { 65 | throw new \RuntimeException('Bad UUID '.$uuid); 66 | } elseif (!$response) { 67 | throw new \RuntimeException('Bad JSON from API: on UUID '.$uuid.' - '.json_last_error_msg()); 68 | } elseif (isset($response->error)) { 69 | throw new \RuntimeException('Error from API: '.$response->error.' on UUID '.$uuid); 70 | } 71 | 72 | return $response; 73 | } 74 | } 75 | --------------------------------------------------------------------------------