mirror of
https://github.com/BushlanovDev/max-bot-api-client-php.git
synced 2026-08-17 12:13:12 +00:00
Added sendMessage method
This commit is contained in:
+49
@@ -4,11 +4,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace BushlanovDev\MaxMessengerBot;
|
||||
|
||||
use BushlanovDev\MaxMessengerBot\Enums\MessageFormat;
|
||||
use BushlanovDev\MaxMessengerBot\Enums\UpdateType;
|
||||
use BushlanovDev\MaxMessengerBot\Exceptions\ClientApiException;
|
||||
use BushlanovDev\MaxMessengerBot\Exceptions\NetworkException;
|
||||
use BushlanovDev\MaxMessengerBot\Exceptions\SerializationException;
|
||||
use BushlanovDev\MaxMessengerBot\Models\BotInfo;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Message;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Result;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Subscription;
|
||||
use InvalidArgumentException;
|
||||
@@ -28,6 +30,7 @@ class Api
|
||||
|
||||
private const string ACTION_ME = '/me';
|
||||
private const string ACTION_SUBSCRIPTIONS = '/subscriptions';
|
||||
private const string ACTION_MESSAGES = '/messages';
|
||||
|
||||
private readonly ClientApiInterface $client;
|
||||
|
||||
@@ -145,4 +148,50 @@ class Api
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to a chat.
|
||||
*
|
||||
* @param int|null $userId Fill this parameter if you want to send message to user.
|
||||
* @param int|null $chatId Fill this if you send message to chat.
|
||||
* @param string|null $text Message text.
|
||||
* @param bool $notify If false, chat participants would not be notified.
|
||||
* @param bool $disableLinkPreview If false, server will not generate media preview for links in text.
|
||||
*
|
||||
* @return Message
|
||||
*
|
||||
* @throws ClientApiException
|
||||
* @throws NetworkException
|
||||
* @throws SerializationException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function sendMessage(
|
||||
?int $userId = null,
|
||||
?int $chatId = null,
|
||||
?string $text = null,
|
||||
?MessageFormat $format = null,
|
||||
bool $notify = true,
|
||||
bool $disableLinkPreview = false,
|
||||
): Message {
|
||||
$query = [
|
||||
'user_id' => $userId,
|
||||
'chat_id' => $chatId,
|
||||
'disable_link_preview' => $disableLinkPreview,
|
||||
];
|
||||
|
||||
$body = [
|
||||
'text' => $text,
|
||||
'format' => $format?->value,
|
||||
'notify' => $notify,
|
||||
];
|
||||
|
||||
$response = $this->client->request(
|
||||
self::METHOD_POST,
|
||||
self::ACTION_MESSAGES,
|
||||
array_filter($query, fn($item) => null !== $item),
|
||||
array_filter($body, fn($item) => null !== $item),
|
||||
);
|
||||
|
||||
return $this->modelFactory->createMessage($response['message']);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -119,7 +119,7 @@ final class Client implements ClientApiInterface
|
||||
$errorCode = $data['code'] ?? 'unknown';
|
||||
$errorMessage = $data['message'] ?? 'An unknown error occurred.';
|
||||
|
||||
$exception = match ($statusCode) {
|
||||
throw match ($statusCode) {
|
||||
401 => new UnauthorizedException($errorMessage, $errorCode, $response),
|
||||
403 => new ForbiddenException($errorMessage, $errorCode, $response),
|
||||
404 => new NotFoundException($errorMessage, $errorCode, $response),
|
||||
@@ -127,7 +127,5 @@ final class Client implements ClientApiInterface
|
||||
429 => new RateLimitExceededException($errorMessage, $errorCode, $response),
|
||||
default => new ClientApiException($errorMessage, $errorCode, $response, $statusCode),
|
||||
};
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BushlanovDev\MaxMessengerBot\Enums;
|
||||
|
||||
enum MessageFormat: string
|
||||
{
|
||||
case Markdown = 'markdown';
|
||||
case Html = 'html';
|
||||
}
|
||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace BushlanovDev\MaxMessengerBot;
|
||||
|
||||
use BushlanovDev\MaxMessengerBot\Models\BotInfo;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Message;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Result;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Subscription;
|
||||
use ReflectionException;
|
||||
@@ -20,6 +21,7 @@ class ModelFactory
|
||||
* @param array<string, mixed> $data
|
||||
*
|
||||
* @return Result
|
||||
*
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function createResult(array $data): Result
|
||||
@@ -33,6 +35,7 @@ class ModelFactory
|
||||
* @param array<string, mixed> $data
|
||||
*
|
||||
* @return BotInfo
|
||||
*
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function createBotInfo(array $data): BotInfo
|
||||
@@ -46,6 +49,7 @@ class ModelFactory
|
||||
* @param array<string, mixed> $data
|
||||
*
|
||||
* @return Subscription
|
||||
*
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function createSubscription(array $data): Subscription
|
||||
@@ -67,4 +71,18 @@ class ModelFactory
|
||||
? array_map([$this, 'createSubscription'], $data['subscriptions'])
|
||||
: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Message.
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
*
|
||||
* @return Message
|
||||
*
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function createMessage(array $data): Message
|
||||
{
|
||||
return Message::fromArray($data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BushlanovDev\MaxMessengerBot\Models;
|
||||
|
||||
/**
|
||||
* Message.
|
||||
*/
|
||||
final readonly class Message extends AbstractModel
|
||||
{
|
||||
/**
|
||||
* @param MessageBody $body Body of created message. Text + attachments.
|
||||
*/
|
||||
public function __construct(
|
||||
public MessageBody $body,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BushlanovDev\MaxMessengerBot\Models;
|
||||
|
||||
/**
|
||||
* Body of created message. Text + attachments.
|
||||
*/
|
||||
final readonly class MessageBody extends AbstractModel
|
||||
{
|
||||
/**
|
||||
* @param string $mid Unique identifier of message.
|
||||
* @param int $seq Sequence identifier of message in chat.
|
||||
* @param string|null $text Message text.
|
||||
*/
|
||||
public function __construct(
|
||||
public string $mid,
|
||||
public int $seq,
|
||||
public ?string $text,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,12 @@ namespace BushlanovDev\MaxMessengerBot\Tests;
|
||||
use BushlanovDev\MaxMessengerBot\Api;
|
||||
use BushlanovDev\MaxMessengerBot\Client;
|
||||
use BushlanovDev\MaxMessengerBot\ClientApiInterface;
|
||||
use BushlanovDev\MaxMessengerBot\Enums\MessageFormat;
|
||||
use BushlanovDev\MaxMessengerBot\Enums\UpdateType;
|
||||
use BushlanovDev\MaxMessengerBot\ModelFactory;
|
||||
use BushlanovDev\MaxMessengerBot\Models\BotInfo;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Message;
|
||||
use BushlanovDev\MaxMessengerBot\Models\MessageBody;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Result;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Subscription;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
@@ -25,6 +28,8 @@ use ReflectionClass;
|
||||
#[UsesClass(Client::class)]
|
||||
#[UsesClass(BotInfo::class)]
|
||||
#[UsesClass(Subscription::class)]
|
||||
#[UsesClass(Message::class)]
|
||||
#[UsesClass(MessageBody::class)]
|
||||
final class ApiTest extends TestCase
|
||||
{
|
||||
private MockObject&ClientApiInterface $clientMock;
|
||||
@@ -214,4 +219,57 @@ final class ApiTest extends TestCase
|
||||
$result = $this->api->unsubscribe($url);
|
||||
$this->assertSame($expectedResultObject, $result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function sendMessageBuildsCorrectRequestForAllParameters(): void
|
||||
{
|
||||
$chatId = 123456;
|
||||
$text = 'Hello, **world**!';
|
||||
$format = MessageFormat::Markdown;
|
||||
$notify = false;
|
||||
$disableLinkPreview = true;
|
||||
|
||||
$expectedQuery = [
|
||||
'chat_id' => $chatId,
|
||||
'disable_link_preview' => $disableLinkPreview,
|
||||
];
|
||||
|
||||
$expectedBody = [
|
||||
'text' => $text,
|
||||
'format' => $format->value,
|
||||
'notify' => $notify,
|
||||
];
|
||||
|
||||
$apiResponse = [
|
||||
'message' => [
|
||||
'body' => ['mid' => 'mid.456.xyz', 'seq' => 101, 'text' => $text],
|
||||
'timestamp' => time(),
|
||||
]
|
||||
];
|
||||
|
||||
$expectedMessageObject = Message::fromArray($apiResponse['message']);
|
||||
|
||||
$this->clientMock
|
||||
->expects($this->once())
|
||||
->method('request')
|
||||
->with('POST', '/messages', $expectedQuery, $expectedBody)
|
||||
->willReturn($apiResponse);
|
||||
|
||||
$this->modelFactoryMock
|
||||
->expects($this->once())
|
||||
->method('createMessage')
|
||||
->with($apiResponse['message'])
|
||||
->willReturn($expectedMessageObject);
|
||||
|
||||
$result = $this->api->sendMessage(
|
||||
null,
|
||||
$chatId,
|
||||
$text,
|
||||
$format,
|
||||
$notify,
|
||||
$disableLinkPreview,
|
||||
);
|
||||
|
||||
$this->assertSame($expectedMessageObject, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ use BushlanovDev\MaxMessengerBot\Enums\UpdateType;
|
||||
use BushlanovDev\MaxMessengerBot\ModelFactory;
|
||||
use BushlanovDev\MaxMessengerBot\Models\BotCommand;
|
||||
use BushlanovDev\MaxMessengerBot\Models\BotInfo;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Message;
|
||||
use BushlanovDev\MaxMessengerBot\Models\MessageBody;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Result;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Subscription;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
@@ -22,6 +24,8 @@ use PHPUnit\Framework\TestCase;
|
||||
#[UsesClass(Result::class)]
|
||||
#[UsesClass(Subscription::class)]
|
||||
#[UsesClass(ArrayOf::class)]
|
||||
#[UsesClass(Message::class)]
|
||||
#[UsesClass(MessageBody::class)]
|
||||
final class ModelFactoryTest extends TestCase
|
||||
{
|
||||
private ModelFactory $factory;
|
||||
@@ -134,4 +138,21 @@ final class ModelFactoryTest extends TestCase
|
||||
$this->assertInstanceOf(Subscription::class, $subscriptions[0]);
|
||||
$this->assertSame(UpdateType::MessageCreated, $subscriptions[0]->updateTypes[0]);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function createMessage(): void
|
||||
{
|
||||
$rawData = [
|
||||
'body' => [
|
||||
'mid' => 'mid.456.xyz',
|
||||
'seq' => 101,
|
||||
'text' => 'Hello, **world**!',
|
||||
],
|
||||
];
|
||||
|
||||
$message = $this->factory->createMessage($rawData);
|
||||
|
||||
$this->assertInstanceOf(Message::class, $message);
|
||||
$this->assertInstanceOf(MessageBody::class, $message->body);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BushlanovDev\MaxMessengerBot\Tests\Models;
|
||||
|
||||
use BushlanovDev\MaxMessengerBot\Models\MessageBody;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
#[CoversClass(MessageBody::class)]
|
||||
final class MessageBodyTest extends TestCase
|
||||
{
|
||||
#[Test]
|
||||
public function canBeCreatedFromArrayWithAllData(): void
|
||||
{
|
||||
$data = [
|
||||
'mid' => 'mid.456.xyz',
|
||||
'seq' => 101,
|
||||
'text' => 'Hello, **world**!',
|
||||
];
|
||||
|
||||
$messageBody = MessageBody::fromArray($data);
|
||||
|
||||
$this->assertInstanceOf(MessageBody::class, $messageBody);
|
||||
$this->assertSame($data['mid'], $messageBody->mid);
|
||||
$this->assertSame($data['seq'], $messageBody->seq);
|
||||
$this->assertSame($data['text'], $messageBody->text);
|
||||
|
||||
$array = $messageBody->toArray();
|
||||
|
||||
$this->assertIsArray($array);
|
||||
$this->assertSame($data, $array);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function canBeCreatedFromArrayWithOptionalDataNull(): void
|
||||
{
|
||||
$data = [
|
||||
'mid' => 'mid.456.xyz',
|
||||
'seq' => 101,
|
||||
'text' => null,
|
||||
];
|
||||
|
||||
$messageBody = MessageBody::fromArray($data);
|
||||
|
||||
$this->assertInstanceOf(MessageBody::class, $messageBody);
|
||||
$this->assertSame($data['mid'], $messageBody->mid);
|
||||
$this->assertSame($data['seq'], $messageBody->seq);
|
||||
$this->assertNull($messageBody->text);
|
||||
|
||||
$array = $messageBody->toArray();
|
||||
|
||||
$this->assertIsArray($array);
|
||||
$this->assertSame($data, $array);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BushlanovDev\MaxMessengerBot\Tests\Models;
|
||||
|
||||
use BushlanovDev\MaxMessengerBot\Models\Message;
|
||||
use BushlanovDev\MaxMessengerBot\Models\MessageBody;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\Attributes\UsesClass;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
#[CoversClass(Message::class)]
|
||||
#[UsesClass(MessageBody::class)]
|
||||
final class MessageTest extends TestCase
|
||||
{
|
||||
#[Test]
|
||||
public function canBeCreatedFromArrayWithAllData(): void
|
||||
{
|
||||
$data = [
|
||||
'body' => [
|
||||
'mid' => 'mid.456.xyz',
|
||||
'seq' => 101,
|
||||
'text' => 'Hello, **world**!',
|
||||
],
|
||||
];
|
||||
|
||||
$message = Message::fromArray($data);
|
||||
|
||||
$this->assertInstanceOf(Message::class, $message);
|
||||
$this->assertInstanceOf(MessageBody::class, $message->body);
|
||||
|
||||
$array = $message->toArray();
|
||||
|
||||
$this->assertIsArray($array);
|
||||
$this->assertSame($data, $array);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user