Skip to content
Merged

I12 #14

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Api.php
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ public function sendMessage(
$this->buildNewMessageBody($text, $attachments, $format, $link, $notify),
);

return $this->modelFactory->createMessage($response['message']);
return $this->modelFactory->createMessageFromSendResponse($response);
}

/**
Expand Down
31 changes: 30 additions & 1 deletion src/ModelFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,33 @@ public function createSubscriptions(array $data): array
: [];
}

/**
* Creates a Message from the specific response structure of the sendMessage endpoint.
*
* @param array<string, mixed> $data The raw response from the client.
*
* @return Message
* @throws ReflectionException
*/
public function createMessageFromSendResponse(array $data): Message
{
$messageData = $data['message'];

$topLevelData = [
'chat_id' => $data['chat_id'] ?? null,
'recipient_id' => $data['recipient_id'] ?? null,
'message_id' => $data['message_id'] ?? null,
];
$messageData = array_merge($messageData, array_filter($topLevelData, fn($value) => $value !== null));

if (isset($messageData['message']) && is_array($messageData['message'])) {
$messageData['body'] = $messageData['message'];
unset($messageData['message']);
}

return $this->createMessage($messageData);
}

/**
* Message.
*
Expand Down Expand Up @@ -267,7 +294,9 @@ public function createInlineButton(array $data): AbstractInlineButton
InlineButtonType::RequestGeoLocation => RequestGeoLocationButton::fromArray($data),
InlineButtonType::Chat => ChatButton::fromArray($data),
InlineButtonType::OpenApp => OpenAppButton::fromArray($data),
default => throw new LogicException('Unknown or unsupported inline button type: ' . ($data['type'] ?? 'none')),
default => throw new LogicException(
'Unknown or unsupported inline button type: ' . ($data['type'] ?? 'none')
),
};
}

Expand Down
6 changes: 6 additions & 0 deletions src/Models/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
* @param string|null $url Message public URL. Can be null for dialogs or non-public chats/channels.
* @param LinkedMessage|null $link Forwarded or replied message.
* @param MessageStat|null $stat Message statistics. Available only for channels.
* @param int|null $chatId Chat identifier.
* @param int|null $recipientId User identifier, if message was sent to user.
* @param string|null $messageId Unique identifier of message.
*/
public function __construct(
public int $timestamp,
Expand All @@ -26,6 +29,9 @@ public function __construct(
public ?string $url,
public ?LinkedMessage $link,
public ?MessageStat $stat,
public ?int $chatId = null,
public ?int $recipientId = null,
public ?string $messageId = null,
) {
}
}
77 changes: 52 additions & 25 deletions tests/ApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ public function sendMessageBuildsCorrectRequestForAllParameters(): void
$apiResponse = [
'message' => [
'timestamp' => time(),
'body' => ['mid' => 'mid.456.xyz', 'seq' => 101, 'text' => $text],
'message' => ['mid' => 'mid.456.xyz', 'seq' => 101, 'text' => $text],
'recipient' => ['chat_type' => 'dialog', 'user_id' => 123, 'chat_id' => null],
'sender' => [
'user_id' => 123,
Expand All @@ -348,9 +348,18 @@ public function sendMessageBuildsCorrectRequestForAllParameters(): void
],
'url' => 'https://max.ru/message/123',
],
'chat_id' => 20414985,
'recipient_id' => 4328369,
'message_id' => 'mid.456.xyz',
];

$expectedMessageObject = Message::fromArray($apiResponse['message']);
$finalMessageData = $apiResponse['message'];
$finalMessageData['body'] = $finalMessageData['message'];
unset($finalMessageData['message']);
$finalMessageData['chat_id'] = $apiResponse['chat_id'];
$finalMessageData['recipient_id'] = $apiResponse['recipient_id'];
$finalMessageData['message_id'] = $apiResponse['message_id'];
$expectedMessageObject = Message::fromArray($finalMessageData);

$this->clientMock
->expects($this->once())
Expand All @@ -360,8 +369,8 @@ public function sendMessageBuildsCorrectRequestForAllParameters(): void

$this->modelFactoryMock
->expects($this->once())
->method('createMessage')
->with($apiResponse['message'])
->method('createMessageFromSendResponse')
->with($apiResponse)
->willReturn($expectedMessageObject);

$result = $this->api->sendMessage(
Expand Down Expand Up @@ -416,12 +425,17 @@ public function sendMessageWithAttachmentsBuildsCorrectRequest(): void
$apiResponse = [
'message' => [
'timestamp' => time(),
'body' => ['mid' => 'mid.test.123', 'seq' => 1, 'text' => $text],
'message' => ['mid' => 'mid.test.123', 'seq' => 1, 'text' => $text],
'recipient' => ['chat_type' => 'dialog', 'user_id' => 123, 'chat_id' => null],
]
],
'message_id' => 'mid.test.123',
];

$expectedMessageObject = Message::fromArray($apiResponse['message']);
$finalMessageData = $apiResponse['message'];
$finalMessageData['body'] = $finalMessageData['message'];
unset($finalMessageData['message']);
$finalMessageData['message_id'] = $apiResponse['message_id'];
$expectedMessageObject = Message::fromArray($finalMessageData);

$this->clientMock
->expects($this->once())
Expand All @@ -436,8 +450,8 @@ public function sendMessageWithAttachmentsBuildsCorrectRequest(): void

$this->modelFactoryMock
->expects($this->once())
->method('createMessage')
->with($apiResponse['message'])
->method('createMessageFromSendResponse')
->with($apiResponse)
->willReturn($expectedMessageObject);

$result = $this->api->sendMessage(
Expand Down Expand Up @@ -803,20 +817,24 @@ public function sendMessageWithStickerAttachmentBuildsCorrectRequest(): void
$apiResponse = [
'message' => [
'timestamp' => time(),
'body' => ['mid' => 'mid.sticker.1', 'seq' => 10],
'message' => ['mid' => 'mid.sticker.1', 'seq' => 10],
'recipient' => ['chat_type' => 'dialog', 'user_id' => $chatId],
]
];
$expectedMessageObject = Message::fromArray($apiResponse['message']);

$finalMessageData = $apiResponse['message'];
$finalMessageData['body'] = $finalMessageData['message'];
unset($finalMessageData['message']);
$expectedMessageObject = Message::fromArray($finalMessageData);

$this->clientMock->expects($this->once())
->method('request')
->with('POST', '/messages', $expectedQuery, $expectedBody)
->willReturn($apiResponse);

$this->modelFactoryMock->expects($this->once())
->method('createMessage')
->with($apiResponse['message'])
->method('createMessageFromSendResponse')
->with($apiResponse)
->willReturn($expectedMessageObject);

$result = $this->api->sendMessage(chatId: $chatId, attachments: [$stickerRequest]);
Expand Down Expand Up @@ -849,20 +867,23 @@ public function sendMessageWithContactAttachmentBuildsCorrectRequest(): void
$apiResponse = [
'message' => [
'timestamp' => time(),
'body' => ['mid' => 'mid.contact.1', 'seq' => 11],
'message' => ['mid' => 'mid.contact.1', 'seq' => 11],
'recipient' => ['chat_type' => 'dialog', 'user_id' => $chatId],
]
];
$expectedMessageObject = Message::fromArray($apiResponse['message']);
$finalMessageData = $apiResponse['message'];
$finalMessageData['body'] = $finalMessageData['message'];
unset($finalMessageData['message']);
$expectedMessageObject = Message::fromArray($finalMessageData);

$this->clientMock->expects($this->once())
->method('request')
->with('POST', '/messages', $expectedQuery, $expectedBody)
->willReturn($apiResponse);

$this->modelFactoryMock->expects($this->once())
->method('createMessage')
->with($apiResponse['message'])
->method('createMessageFromSendResponse')
->with($apiResponse)
->willReturn($expectedMessageObject);

$result = $this->api->sendMessage(chatId: $chatId, attachments: [$contactRequest]);
Expand Down Expand Up @@ -895,20 +916,23 @@ public function sendMessageWithLocationAttachmentBuildsCorrectRequest(): void
$apiResponse = [
'message' => [
'timestamp' => time(),
'body' => ['mid' => 'mid.location.1', 'seq' => 12],
'message' => ['mid' => 'mid.location.1', 'seq' => 12],
'recipient' => ['chat_type' => 'dialog', 'user_id' => $chatId],
]
];
$expectedMessageObject = Message::fromArray($apiResponse['message']);
$finalMessageData = $apiResponse['message'];
$finalMessageData['body'] = $finalMessageData['message'];
unset($finalMessageData['message']);
$expectedMessageObject = Message::fromArray($finalMessageData);

$this->clientMock->expects($this->once())
->method('request')
->with('POST', '/messages', $expectedQuery, $expectedBody)
->willReturn($apiResponse);

$this->modelFactoryMock->expects($this->once())
->method('createMessage')
->with($apiResponse['message'])
->method('createMessageFromSendResponse')
->with($apiResponse)
->willReturn($expectedMessageObject);

$result = $this->api->sendMessage(chatId: $chatId, attachments: [$locationRequest]);
Expand Down Expand Up @@ -940,20 +964,23 @@ public function sendMessageWithShareAttachmentBuildsCorrectRequest(): void
$apiResponse = [
'message' => [
'timestamp' => time(),
'body' => ['mid' => 'mid.share.1', 'seq' => 13],
'message' => ['mid' => 'mid.share.1', 'seq' => 13],
'recipient' => ['chat_type' => 'dialog', 'user_id' => $chatId],
]
];
$expectedMessageObject = Message::fromArray($apiResponse['message']);
$finalMessageData = $apiResponse['message'];
$finalMessageData['body'] = $finalMessageData['message'];
unset($finalMessageData['message']);
$expectedMessageObject = Message::fromArray($finalMessageData);

$this->clientMock->expects($this->once())
->method('request')
->with('POST', '/messages', $expectedQuery, $expectedBody)
->willReturn($apiResponse);

$this->modelFactoryMock->expects($this->once())
->method('createMessage')
->with($apiResponse['message'])
->method('createMessageFromSendResponse')
->with($apiResponse)
->willReturn($expectedMessageObject);

$result = $this->api->sendMessage(chatId: $chatId, attachments: [$shareRequest]);
Expand Down
30 changes: 30 additions & 0 deletions tests/ModelFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,36 @@ public function createSubscriptions(): void
$this->assertSame(UpdateType::MessageCreated, $subscriptions[0]->updateTypes[0]);
}

#[Test]
public function createMessageFromSendResponseCorrectlyTransformsData(): void
{
$apiResponse = [
'message' => [
'recipient' => ['chat_id' => 20414985, 'chat_type' => 'dialog', 'user_id' => 4328369],
'timestamp' => 1760089962345,
'sender' => [
'user_id' => 24480184,
'first_name' => 'Autobot',
'is_bot' => true,
'last_activity_time' => 1760089962354,
],
'message' => ['mid' => 'mid.xyz', 'seq' => 1153, 'text' => '123123'],
],
'chat_id' => 20414985,
'recipient_id' => 4328369,
'message_id' => 'mid.xyz',
];

$message = $this->factory->createMessageFromSendResponse($apiResponse);

$this->assertInstanceOf(Message::class, $message);
$this->assertInstanceOf(MessageBody::class, $message->body);
$this->assertSame('mid.xyz', $message->body->mid);
$this->assertSame(20414985, $message->chatId);
$this->assertSame(4328369, $message->recipientId);
$this->assertSame('mid.xyz', $message->messageId);
}

#[Test]
public function createMessage(): void
{
Expand Down
3 changes: 3 additions & 0 deletions tests/Models/MessageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ public function canBeCreatedFromArrayWithAllData(): void
'stat' => [
'views' => 500,
],
'chat_id' => null,
'recipient_id' => null,
'message_id' => null,
];

$message = Message::fromArray($data);
Expand Down