From 028d2591f8563fbb16175c6c58b11c1f00bfd404 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 17 Jul 2025 19:15:59 +0300 Subject: [PATCH] Added attachment RequestContactButton & RequestGeoLocationButton --- README.md | 1 - src/Api.php | 5 ++ src/Client.php | 16 +++---- .../Attachments/Buttons/CallbackButton.php | 3 ++ src/Models/Attachments/Buttons/LinkButton.php | 3 ++ .../Buttons/RequestContactButton.php | 21 +++++++++ .../Buttons/RequestGeoLocationButton.php | 26 ++++++++++ tests/ClientTest.php | 3 +- .../Buttons/RequestContactTest.php | 30 ++++++++++++ .../Buttons/RequestGeoLocationTest.php | 47 +++++++++++++++++++ 10 files changed, 145 insertions(+), 10 deletions(-) create mode 100644 src/Models/Attachments/Buttons/RequestContactButton.php create mode 100644 src/Models/Attachments/Buttons/RequestGeoLocationButton.php create mode 100644 tests/Models/Attachments/Buttons/RequestContactTest.php create mode 100644 tests/Models/Attachments/Buttons/RequestGeoLocationTest.php diff --git a/README.md b/README.md index 0971ad8..98fe3a9 100644 --- a/README.md +++ b/README.md @@ -16,4 +16,3 @@ Откройте диалог с [MasterBot](https://max.ru/MasterBot), следуйте инструкциям и создайте нового бота. После создания бота MasterBot отправит вам токен. - diff --git a/src/Api.php b/src/Api.php index d968faf..ecf777d 100644 --- a/src/Api.php +++ b/src/Api.php @@ -26,6 +26,9 @@ use ReflectionException; */ class Api { + private const string API_BASE_URL = 'https://botapi.max.ru'; + public const string API_VERSION = '0.0.6'; + private const string METHOD_GET = 'GET'; private const string METHOD_POST = 'POST'; private const string METHOD_DELETE = 'DELETE'; @@ -57,6 +60,8 @@ class Api new \GuzzleHttp\Client(), new \GuzzleHttp\Psr7\HttpFactory(), new \GuzzleHttp\Psr7\HttpFactory(), + self::API_BASE_URL, + self::API_VERSION, ); $this->modelFactory = $modelFactory ?? new ModelFactory(); } diff --git a/src/Client.php b/src/Client.php index 46b8bb9..fd3e8b1 100644 --- a/src/Client.php +++ b/src/Client.php @@ -27,16 +27,13 @@ use Psr\Http\Message\StreamFactoryInterface; */ final class Client implements ClientApiInterface { - private const string API_BASE_URL = 'https://botapi.max.ru'; - - private const string DEFAULT_API_VERSION = '0.0.6'; - /** * @param string $accessToken Your bot's access token from @MasterBot. * @param ClientInterface $httpClient A PSR-18 compatible HTTP client (e.g., Guzzle). * @param RequestFactoryInterface $requestFactory A PSR-17 factory for creating requests. * @param StreamFactoryInterface $streamFactory A PSR-17 factory for creating request body streams. - * @param string $apiVersion The API version to use for requests. + * @param string $baseUrl The base URL for API requests. + * @param string|null $apiVersion The API version to use for requests. * * @throws InvalidArgumentException */ @@ -45,7 +42,8 @@ final class Client implements ClientApiInterface private readonly ClientInterface $httpClient, private readonly RequestFactoryInterface $requestFactory, private readonly StreamFactoryInterface $streamFactory, - private readonly string $apiVersion = self::DEFAULT_API_VERSION, + private readonly string $baseUrl, + private readonly ?string $apiVersion = null, ) { if (empty($accessToken)) { throw new InvalidArgumentException('Access token cannot be empty.'); @@ -58,9 +56,11 @@ final class Client implements ClientApiInterface public function request(string $method, string $uri, array $queryParams = [], array $body = []): array { $queryParams['access_token'] = $this->accessToken; - $queryParams['v'] = $this->apiVersion; + if (!empty($this->apiVersion)) { + $queryParams['v'] = $this->apiVersion; + } - $fullUrl = self::API_BASE_URL . $uri . '?' . http_build_query($queryParams); + $fullUrl = $this->baseUrl . $uri . '?' . http_build_query($queryParams); $request = $this->requestFactory->createRequest($method, $fullUrl); if (!empty($body)) { diff --git a/src/Models/Attachments/Buttons/CallbackButton.php b/src/Models/Attachments/Buttons/CallbackButton.php index a539dbb..e30bbea 100644 --- a/src/Models/Attachments/Buttons/CallbackButton.php +++ b/src/Models/Attachments/Buttons/CallbackButton.php @@ -7,6 +7,9 @@ namespace BushlanovDev\MaxMessengerBot\Models\Attachments\Buttons; use BushlanovDev\MaxMessengerBot\Enums\ButtonType; use BushlanovDev\MaxMessengerBot\Enums\Intent; +/** + * Sends a notification with payload to a bot (via WebHook or long polling). + */ final readonly class CallbackButton extends AbstractButton { public string $payload; diff --git a/src/Models/Attachments/Buttons/LinkButton.php b/src/Models/Attachments/Buttons/LinkButton.php index a6d98d2..21f538a 100644 --- a/src/Models/Attachments/Buttons/LinkButton.php +++ b/src/Models/Attachments/Buttons/LinkButton.php @@ -6,6 +6,9 @@ namespace BushlanovDev\MaxMessengerBot\Models\Attachments\Buttons; use BushlanovDev\MaxMessengerBot\Enums\ButtonType; +/** + * Makes a user to follow a link. + */ final readonly class LinkButton extends AbstractButton { public string $url; diff --git a/src/Models/Attachments/Buttons/RequestContactButton.php b/src/Models/Attachments/Buttons/RequestContactButton.php new file mode 100644 index 0000000..5b4a8ba --- /dev/null +++ b/src/Models/Attachments/Buttons/RequestContactButton.php @@ -0,0 +1,21 @@ +quick = $quick; + } +} diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 9f90ec7..b0af670 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -74,6 +74,7 @@ final class ClientTest extends TestCase $this->httpClientMock, $this->requestFactoryMock, $this->streamFactoryMock, + self::API_BASE_URL, self::API_VERSION, ); } @@ -84,7 +85,7 @@ final class ClientTest extends TestCase $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Access token cannot be empty.'); - new Client('', $this->httpClientMock, $this->requestFactoryMock, $this->streamFactoryMock); + new Client('', $this->httpClientMock, $this->requestFactoryMock, $this->streamFactoryMock, '', ''); } #[Test] diff --git a/tests/Models/Attachments/Buttons/RequestContactTest.php b/tests/Models/Attachments/Buttons/RequestContactTest.php new file mode 100644 index 0000000..e13b344 --- /dev/null +++ b/tests/Models/Attachments/Buttons/RequestContactTest.php @@ -0,0 +1,30 @@ + ButtonType::RequestContact->value, + 'text' => 'Test Button', + ]; + + $resultArray = $button->toArray(); + + $this->assertSame($expectedArray, $resultArray); + } +} diff --git a/tests/Models/Attachments/Buttons/RequestGeoLocationTest.php b/tests/Models/Attachments/Buttons/RequestGeoLocationTest.php new file mode 100644 index 0000000..77d2c66 --- /dev/null +++ b/tests/Models/Attachments/Buttons/RequestGeoLocationTest.php @@ -0,0 +1,47 @@ + false, + 'type' => ButtonType::RequestGeoLocation->value, + 'text' => 'Test Button', + ]; + + $resultArray = $button->toArray(); + + $this->assertSame($expectedArray, $resultArray); + } + + #[Test] + public function toArraySerializesCorrectlyWithQuick(): void + { + $button = new RequestGeoLocationButton('Test Button', true); + + $expectedArray = [ + 'quick' => true, + 'type' => ButtonType::RequestGeoLocation->value, + 'text' => 'Test Button', + ]; + + $resultArray = $button->toArray(); + + $this->assertSame($expectedArray, $resultArray); + } +}