Implemented "ely/mojang-api"

This commit is contained in:
Arslan
2019-05-09 04:23:49 +03:00
parent b3eff9302c
commit 85d4d465fb
10 changed files with 110 additions and 255 deletions

View File

@@ -1,56 +0,0 @@
<?php
namespace common\components\Mojang;
use common\components\Mojang\exceptions\MojangApiException;
use common\components\Mojang\exceptions\NoContentException;
use common\components\Mojang\response\UsernameToUUIDResponse;
use Yii;
class Api {
/**
* @param string $username
* @param int $atTime
*
* @return UsernameToUUIDResponse
* @throws MojangApiException
* @throws NoContentException|\GuzzleHttp\Exception\RequestException
* @url http://wiki.vg/Mojang_API#Username_-.3E_UUID_at_time
*/
public function usernameToUUID($username, $atTime = null) {
$query = [];
if ($atTime !== null) {
$query['atTime'] = $atTime;
}
$response = $this->getClient()->get($this->buildUsernameToUUIDRoute($username), $query);
if ($response->getStatusCode() === 204) {
throw new NoContentException('Username not found');
}
if ($response->getStatusCode() !== 200) {
throw new MojangApiException('Unexpected request result');
}
$data = json_decode($response->getBody(), true);
$responseObj = new UsernameToUUIDResponse();
$responseObj->id = $data['id'];
$responseObj->name = $data['name'];
$responseObj->legacy = isset($data['legacy']);
$responseObj->demo = isset($data['demo']);
return $responseObj;
}
/**
* @return \GuzzleHttp\Client
*/
protected function getClient() {
return Yii::$app->guzzle;
}
protected function buildUsernameToUUIDRoute($username) {
return 'https://api.mojang.com/users/profiles/minecraft/' . $username;
}
}

View File

@@ -1,8 +0,0 @@
<?php
namespace common\components\Mojang\exceptions;
use Exception;
class MojangApiException extends Exception {
}

View File

@@ -1,6 +0,0 @@
<?php
namespace common\components\Mojang\exceptions;
class NoContentException extends MojangApiException {
}

View File

@@ -1,29 +0,0 @@
<?php
namespace common\components\Mojang\response;
/**
* http://wiki.vg/Mojang_API#Username_-.3E_UUID_at_time
*/
class UsernameToUUIDResponse {
/**
* @var string uuid пользователя без разделения на дефисы
*/
public $id;
/**
* @var string ник пользователя в настоящем времени
*/
public $name;
/**
* @var bool если имеет значение true, то значит аккаунт не мигрирован в Mojang аккаунт
*/
public $legacy = false;
/**
* @var bool будет иметь значение true, если аккаунт находится в демо-режиме (не приобретена лицензия)
*/
public $demo = false;
}

View File

@@ -18,6 +18,7 @@ return [
'container' => [
'definitions' => [
GuzzleHttp\ClientInterface::class => GuzzleHttp\Client::class,
Ely\Mojang\Api::class => Ely\Mojang\Api::class,
],
],
'components' => [

View File

@@ -4,12 +4,12 @@ declare(strict_types=1);
namespace common\tasks;
use api\exceptions\ThisShouldNotHappenException;
use common\components\Mojang\Api as MojangApi;
use common\components\Mojang\exceptions\MojangApiException;
use common\components\Mojang\exceptions\NoContentException;
use common\models\Account;
use common\models\MojangUsername;
use GuzzleHttp\Exception\RequestException;
use Ely\Mojang\Api as MojangApi;
use Ely\Mojang\Exception\MojangApiException;
use Ely\Mojang\Exception\NoContentException;
use GuzzleHttp\Exception\GuzzleException;
use Yii;
use yii\queue\JobInterface;
@@ -31,14 +31,15 @@ class PullMojangUsername implements JobInterface {
*/
public function execute($queue) {
Yii::$app->statsd->inc('queue.pullMojangUsername.attempt');
$mojangApi = $this->createMojangApi();
/** @var MojangApi $mojangApi */
$mojangApi = Yii::$app->get(MojangApi::class);
try {
$response = $mojangApi->usernameToUUID($this->username);
Yii::$app->statsd->inc('queue.pullMojangUsername.found');
} catch (NoContentException $e) {
$response = false;
Yii::$app->statsd->inc('queue.pullMojangUsername.not_found');
} catch (RequestException | MojangApiException $e) {
} catch (GuzzleException | MojangApiException $e) {
Yii::$app->statsd->inc('queue.pullMojangUsername.error');
return;
}
@@ -52,10 +53,10 @@ class PullMojangUsername implements JobInterface {
} else {
if ($mojangUsername === null) {
$mojangUsername = new MojangUsername();
$mojangUsername->username = $response->name;
$mojangUsername->uuid = $response->id;
$mojangUsername->username = $response->getName();
$mojangUsername->uuid = $response->getId();
} else {
$mojangUsername->uuid = $response->id;
$mojangUsername->uuid = $response->getId();
$mojangUsername->touch('last_pulled_at');
}
@@ -65,8 +66,4 @@ class PullMojangUsername implements JobInterface {
}
}
protected function createMojangApi(): MojangApi {
return new MojangApi();
}
}

View File

@@ -1,54 +0,0 @@
<?php
namespace common\tests\unit\components\Mojang;
use common\components\Mojang\Api;
use common\components\Mojang\response\UsernameToUUIDResponse;
use common\tests\unit\TestCase;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use Yii;
class ApiTest extends TestCase {
/**
* @var MockHandler
*/
private $handler;
public function _before() {
parent::_before();
$this->handler = new MockHandler();
$handler = HandlerStack::create($this->handler);
Yii::$app->set('guzzle', new GuzzleClient([
'handler' => $handler,
]));
}
public function testUsernameToUUID() {
$this->handler->append(new Response(200, [], '{"id": "7125ba8b1c864508b92bb5c042ccfe2b","name": "KrisJelbring"}'));
$response = (new Api())->usernameToUUID('KrisJelbring');
$this->assertInstanceOf(UsernameToUUIDResponse::class, $response);
$this->assertSame('7125ba8b1c864508b92bb5c042ccfe2b', $response->id);
$this->assertSame('KrisJelbring', $response->name);
}
/**
* @expectedException \common\components\Mojang\exceptions\NoContentException
*/
public function testUsernameToUUIDNoContent() {
$this->handler->append(new Response(204));
(new Api())->usernameToUUID('some-non-exists-user');
}
/**
* @expectedException \GuzzleHttp\Exception\RequestException
*/
public function testUsernameToUUID404() {
$this->handler->append(new Response(404, [], '{"error":"Not Found","errorMessage":"The server has not found anything matching the request URI"}'));
(new Api())->usernameToUUID('#hashedNickname');
}
}

View File

@@ -3,14 +3,17 @@ declare(strict_types=1);
namespace common\tests\unit\tasks;
use common\components\Mojang\Api;
use common\components\Mojang\exceptions\NoContentException;
use common\components\Mojang\response\UsernameToUUIDResponse;
use common\models\Account;
use common\models\MojangUsername;
use common\tasks\PullMojangUsername;
use common\tests\fixtures\MojangUsernameFixture;
use common\tests\unit\TestCase;
use Ely\Mojang\Api as MojangApi;
use Ely\Mojang\Exception\NoContentException;
use Ely\Mojang\Response\ProfileInfo;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use Yii;
use yii\queue\Queue;
/**
@@ -18,12 +21,8 @@ use yii\queue\Queue;
*/
class PullMojangUsernameTest extends TestCase {
private $expectedResponse;
/**
* @var PullMojangUsername
*/
private $task;
/** @var \PHPUnit\Framework\MockObject\Builder\InvocationMocker */
private $mockedMethod;
public function _fixtures() {
return [
@@ -34,33 +33,11 @@ class PullMojangUsernameTest extends TestCase {
public function _before() {
parent::_before();
/** @var PullMojangUsername|\PHPUnit_Framework_MockObject_MockObject $task */
$task = $this->getMockBuilder(PullMojangUsername::class)
->setMethods(['createMojangApi'])
->getMock();
/** @var \PHPUnit\Framework\MockObject\MockObject|MojangApi $mockApi */
$mockApi = $this->createMock(MojangApi::class);
$this->mockedMethod = $mockApi->method('usernameToUUID');
/** @var Api|\PHPUnit_Framework_MockObject_MockObject $apiMock */
$apiMock = $this->getMockBuilder(Api::class)
->setMethods(['usernameToUUID'])
->getMock();
$apiMock
->expects($this->any())
->method('usernameToUUID')
->willReturnCallback(function() {
if ($this->expectedResponse === false) {
throw new NoContentException();
}
return $this->expectedResponse;
});
$task
->expects($this->any())
->method('createMojangApi')
->willReturn($apiMock);
$this->task = $task;
Yii::$app->set(MojangApi::class, $mockApi);
}
public function testCreateFromAccount() {
@@ -71,15 +48,13 @@ class PullMojangUsernameTest extends TestCase {
}
public function testExecuteUsernameExists() {
$expectedResponse = new UsernameToUUIDResponse();
$expectedResponse->id = '069a79f444e94726a5befca90e38aaf5';
$expectedResponse->name = 'Notch';
$this->expectedResponse = $expectedResponse;
$this->mockedMethod->willReturn(new ProfileInfo('069a79f444e94726a5befca90e38aaf5', 'Notch'));
/** @var \common\models\MojangUsername $mojangUsernameFixture */
$mojangUsernameFixture = $this->tester->grabFixture('mojangUsernames', 'Notch');
$this->task->username = 'Notch';
$this->task->execute(mock(Queue::class));
$task = new PullMojangUsername();
$task->username = 'Notch';
$task->execute(mock(Queue::class));
/** @var MojangUsername|null $mojangUsername */
$mojangUsername = MojangUsername::findOne('Notch');
$this->assertInstanceOf(MojangUsername::class, $mojangUsername);
@@ -88,15 +63,13 @@ class PullMojangUsernameTest extends TestCase {
}
public function testExecuteChangedUsernameExists() {
$expectedResponse = new UsernameToUUIDResponse();
$expectedResponse->id = '069a79f444e94726a5befca90e38aaf5';
$expectedResponse->name = 'Notch';
$this->expectedResponse = $expectedResponse;
$this->mockedMethod->willReturn(new ProfileInfo('069a79f444e94726a5befca90e38aaf5', 'Notch'));
/** @var MojangUsername $mojangUsernameFixture */
$mojangUsernameFixture = $this->tester->grabFixture('mojangUsernames', 'Notch');
$this->task->username = 'Notch';
$this->task->execute(mock(Queue::class));
$task = new PullMojangUsername();
$task->username = 'Notch';
$task->execute(mock(Queue::class));
/** @var MojangUsername|null $mojangUsername */
$mojangUsername = MojangUsername::findOne('Notch');
$this->assertInstanceOf(MojangUsername::class, $mojangUsername);
@@ -105,40 +78,37 @@ class PullMojangUsernameTest extends TestCase {
}
public function testExecuteChangedUsernameNotExists() {
$expectedResponse = new UsernameToUUIDResponse();
$expectedResponse->id = '607153852b8c4909811f507ed8ee737f';
$expectedResponse->name = 'Chest';
$this->expectedResponse = $expectedResponse;
$this->mockedMethod->willReturn(new ProfileInfo('607153852b8c4909811f507ed8ee737f', 'Chest'));
$this->task->username = 'Chest';
$this->task->execute(mock(Queue::class));
$task = new PullMojangUsername();
$task->username = 'Chest';
$task->execute(mock(Queue::class));
/** @var MojangUsername|null $mojangUsername */
$mojangUsername = MojangUsername::findOne('Chest');
$this->assertInstanceOf(MojangUsername::class, $mojangUsername);
}
public function testExecuteRemoveIfExistsNoMore() {
$this->expectedResponse = false;
$this->mockedMethod->willThrowException(new NoContentException(new Request('', ''), new Response()));
$username = $this->tester->grabFixture('mojangUsernames', 'not-exists')['username'];
$this->task->username = $username;
$this->task->execute(mock(Queue::class));
$task = new PullMojangUsername();
$task->username = $username;
$task->execute(mock(Queue::class));
/** @var MojangUsername|null $mojangUsername */
$mojangUsername = MojangUsername::findOne($username);
$this->assertNull($mojangUsername);
}
public function testExecuteUuidUpdated() {
$expectedResponse = new UsernameToUUIDResponse();
$expectedResponse->id = 'f498513ce8c84773be26ecfc7ed5185d';
$expectedResponse->name = 'jeb';
$this->expectedResponse = $expectedResponse;
$this->mockedMethod->willReturn(new ProfileInfo('f498513ce8c84773be26ecfc7ed5185d', 'jeb'));
/** @var MojangUsername $mojangInfo */
$mojangInfo = $this->tester->grabFixture('mojangUsernames', 'uuid-changed');
$username = $mojangInfo['username'];
$this->task->username = $username;
$this->task->execute(mock(Queue::class));
$task = new PullMojangUsername();
$task->username = $username;
$task->execute(mock(Queue::class));
/** @var MojangUsername|null $mojangUsername */
$mojangUsername = MojangUsername::findOne($username);
$this->assertInstanceOf(MojangUsername::class, $mojangUsername);