Skip to content
Merged
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ $handler->handle();
#### Bots

- [x] `GET /me` (`getBotInfo`) - [*Получение информации о боте.*](./docs/README.md#Получение-информации-о-боте)
- [x] `PATCH /me` (`editBotInfo`) - [*Редактирование информации о боте.*](./docs/README.md#Редактирование-информации-о-боте)
- [x] `PATCH /me/commands` (`editBotCommands`) - [*Редактирование команд бота.*](./docs/README.md#Редактирование-команд-бота)
- [x] ~~`PATCH /me` (`editBotInfo`) - [*Редактирование информации о боте.*](./docs/README.md#Редактирование-информации-о-боте-deprecated)~~ (deprecated)

#### Chats

Expand Down
20 changes: 18 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
- [Инициализация бота](#Инициализация-бота)
- [Информация о боте](#Информация-о-боте)
- `GET /me` (`getBotInfo`) - [*Получение информации о боте.*](#Получение-информации-о-боте)
- `PATCH /me` (`editBotInfo`) - [*Редактирование информации о боте.*](#Редактирование-информации-о-боте)
- `PATCH /me/commands` (`editBotCommands`) - [*Редактирование команд бота.*](#Редактирование-команд-бота)
- ~~`PATCH /me` (`editBotInfo`)~~ - [*Редактирование информации о боте.*](#Редактирование-информации-о-боте-deprecated) (deprecated)
- [Чаты](#Чаты)
- ~~`GET /chats` (`getChats`)~~ - [*Получение списка всех чатов бота.*](#Получение-списка-всех-чатов-бота-deprecated) (deprecated)
- `GET /chats/{chatLink}` (`getChatByLink`) - [*Получение информации о чате по ссылке.*](#Получение-информации-о-чате-по-ссылке)
Expand Down Expand Up @@ -119,7 +120,22 @@ $api = new BushlanovDev\MaxMessengerBot\Api(
$botInfo = $api->getBotInfo();
```

### Редактирование информации о боте
### Редактирование команд бота

Задаёт команды, которые пользователь видит подсказками, когда набирает «/». Не больше 32 команд, описание команды
необязательно.

```php
$botCommands = $api->editBotCommands([
new BotCommand('start', 'Начать'),
new BotCommand('help', 'Помощь'),
]);
```

### Редактирование информации о боте (deprecated)

API больше не принимает `PATCH /me` и отвечает `Path /me is not recognized`. Команды задаются методом
[`editBotCommands`](#Редактирование-команд-бота), имя, описание и аватар бота — на платформе MAX для партнёров.

Обратите внимание, что данный метод отправляется PATCH запросом. Это значит, что будут обновлены только переданные
поля.
Expand Down
32 changes: 32 additions & 0 deletions src/Api.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use BushlanovDev\MaxMessengerBot\Models\Attachments\Requests\FileAttachmentRequest;
use BushlanovDev\MaxMessengerBot\Models\Attachments\Requests\PhotoAttachmentRequest;
use BushlanovDev\MaxMessengerBot\Models\Attachments\Requests\VideoAttachmentRequest;
use BushlanovDev\MaxMessengerBot\Models\BotCommand;
use BushlanovDev\MaxMessengerBot\Models\BotCommandsInfo;
use BushlanovDev\MaxMessengerBot\Models\BotInfo;
use BushlanovDev\MaxMessengerBot\Models\BotPatch;
use BushlanovDev\MaxMessengerBot\Models\Chat;
Expand Down Expand Up @@ -61,6 +63,7 @@ class Api
private const string METHOD_PUT = 'PUT';

private const string ACTION_ME = '/me';
private const string ACTION_ME_COMMANDS = '/me/commands';
private const string ACTION_SUBSCRIPTIONS = '/subscriptions';
private const string ACTION_MESSAGES = '/messages';
private const string ACTION_UPLOADS = '/uploads';
Expand Down Expand Up @@ -252,6 +255,31 @@ public function getBotInfo(): BotInfo
);
}

/**
* Edits the bot commands shown to users as hints when they type "/".
*
* Example: editBotCommands([new BotCommand('start', 'Start the bot'), new BotCommand('help', 'Help')]);
*
* @param BotCommand[] $commands Up to 32 commands.
*
* @return BotCommandsInfo
* @throws ClientApiException
* @throws NetworkException
* @throws ReflectionException
* @throws SerializationException
*/
public function editBotCommands(array $commands): BotCommandsInfo
{
return $this->modelFactory->createBotCommandsInfo(
$this->client->request(
self::METHOD_PATCH,
self::ACTION_ME_COMMANDS,
[],
['commands' => array_map(static fn(BotCommand $command) => $command->toArray(), $commands)],
)
);
}

/**
* List of all active webhook subscriptions.
*
Expand Down Expand Up @@ -1099,6 +1127,10 @@ public function editMessage(
*
* Example: editBotInfo(new BotPatch(name: 'New Bot Name', description: null));
*
* @deprecated The API no longer accepts `PATCH /me` and answers "Path /me is not recognized".
* Set commands with editBotCommands(); name, description and photo are edited
* on the MAX partner platform.
*
* @param BotPatch $botPatch
*
* @return BotInfo
Expand Down
14 changes: 14 additions & 0 deletions src/ModelFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use BushlanovDev\MaxMessengerBot\Models\Attachments\ShareAttachment;
use BushlanovDev\MaxMessengerBot\Models\Attachments\StickerAttachment;
use BushlanovDev\MaxMessengerBot\Models\Attachments\VideoAttachment;
use BushlanovDev\MaxMessengerBot\Models\BotCommandsInfo;
use BushlanovDev\MaxMessengerBot\Models\BotInfo;
use BushlanovDev\MaxMessengerBot\Models\Chat;
use BushlanovDev\MaxMessengerBot\Models\ChatList;
Expand Down Expand Up @@ -104,6 +105,19 @@ public function createResult(array $data): Result
return Result::fromArray($data);
}

/**
* Commands of the current bot.
*
* @param array<string, mixed> $data
*
* @return BotCommandsInfo
* @throws ReflectionException
*/
public function createBotCommandsInfo(array $data): BotCommandsInfo
{
return BotCommandsInfo::fromArray($data);
}

/**
* Information about the current bot.
*
Expand Down
22 changes: 22 additions & 0 deletions src/Models/BotCommandsInfo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace BushlanovDev\MaxMessengerBot\Models;

use BushlanovDev\MaxMessengerBot\Attributes\ArrayOf;

/**
* Bot commands information.
*/
final readonly class BotCommandsInfo extends AbstractModel
{
/**
* @param BotCommand[]|null $commands Commands supported by the bot (up to 32 elements).
*/
public function __construct(
#[ArrayOf(BotCommand::class)]
public ?array $commands,
) {
}
}
2 changes: 2 additions & 0 deletions src/Models/BotPatch.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* @property-read BotCommand[]|null $commands
* @property-read PhotoAttachmentRequestPayload|null $photo
* @property-read string|null $name @deprecated Use first_name
*
* @deprecated The API no longer accepts `PATCH /me`. Use Api::editBotCommands() for commands.
*/
final readonly class BotPatch extends AbstractPatchModel
{
Expand Down
56 changes: 56 additions & 0 deletions tests/ApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
use BushlanovDev\MaxMessengerBot\Models\Attachments\Requests\ShareAttachmentRequest;
use BushlanovDev\MaxMessengerBot\Models\Attachments\Requests\StickerAttachmentRequest;
use BushlanovDev\MaxMessengerBot\Models\Attachments\Requests\VideoAttachmentRequest;
use BushlanovDev\MaxMessengerBot\Models\BotCommand;
use BushlanovDev\MaxMessengerBot\Models\BotCommandsInfo;
use BushlanovDev\MaxMessengerBot\Models\BotInfo;
use BushlanovDev\MaxMessengerBot\Models\BotPatch;
use BushlanovDev\MaxMessengerBot\Models\Chat;
Expand Down Expand Up @@ -116,6 +118,8 @@
#[UsesClass(ChatMembersList::class)]
#[UsesClass(ChatAdmin::class)]
#[UsesClass(BotPatch::class)]
#[UsesClass(BotCommand::class)]
#[UsesClass(BotCommandsInfo::class)]
#[UsesClass(ChatPatch::class)]
#[UsesClass(VideoAttachmentDetails::class)]
#[UsesClass(VideoUrls::class)]
Expand Down Expand Up @@ -1883,6 +1887,58 @@ public function editMessageCanClearAttachmentsWithEmptyArray(): void
$this->assertSame($expectedResult, $result);
}

#[Test]
public function editBotCommandsSendsCommandsToDedicatedEndpoint(): void
{
$rawResponseData = [
'commands' => [
['name' => 'start', 'description' => 'Start the bot'],
['name' => 'help', 'description' => null],
],
];
$expectedResult = new BotCommandsInfo([
new BotCommand('start', 'Start the bot'),
new BotCommand('help', null),
]);

$this->clientMock
->expects($this->once())
->method('request')
->with('PATCH', '/me/commands', [], $rawResponseData)
->willReturn($rawResponseData);

$this->modelFactoryMock
->expects($this->once())
->method('createBotCommandsInfo')
->with($rawResponseData)
->willReturn($expectedResult);

$result = $this->api->editBotCommands([
new BotCommand('start', 'Start the bot'),
new BotCommand('help', null),
]);

$this->assertSame($expectedResult, $result);
}

#[Test]
public function editBotCommandsSendsAnEmptyList(): void
{
$this->clientMock
->expects($this->once())
->method('request')
->with('PATCH', '/me/commands', [], ['commands' => []])
->willReturn(['commands' => []]);

$this->modelFactoryMock
->expects($this->once())
->method('createBotCommandsInfo')
->with(['commands' => []])
->willReturn(new BotCommandsInfo([]));

$this->api->editBotCommands([]);
}

#[Test]
public function editBotInfoSendsCorrectPatchBody(): void
{
Expand Down
19 changes: 19 additions & 0 deletions tests/ModelFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use BushlanovDev\MaxMessengerBot\Models\Attachments\PhotoAttachment;
use BushlanovDev\MaxMessengerBot\Models\Attachments\ShareAttachment;
use BushlanovDev\MaxMessengerBot\Models\BotCommand;
use BushlanovDev\MaxMessengerBot\Models\BotCommandsInfo;
use BushlanovDev\MaxMessengerBot\Models\BotInfo;
use BushlanovDev\MaxMessengerBot\Models\Chat;
use BushlanovDev\MaxMessengerBot\Models\ChatList;
Expand Down Expand Up @@ -61,6 +62,7 @@
#[CoversClass(ModelFactory::class)]
#[UsesClass(BotInfo::class)]
#[UsesClass(BotCommand::class)]
#[UsesClass(BotCommandsInfo::class)]
#[UsesClass(Result::class)]
#[UsesClass(Subscription::class)]
#[UsesClass(ArrayOf::class)]
Expand Down Expand Up @@ -171,6 +173,23 @@ public function createBotInfoCorrectlyHydratesCommands(): void
$this->assertSame('help', $botInfo->commands[1]->name);
}

#[Test]
public function createBotCommandsInfoHydratesCommands(): void
{
$botCommands = $this->factory->createBotCommandsInfo([
'commands' => [
['name' => 'start', 'description' => 'Start the bot'],
['name' => 'help', 'description' => null],
],
]);

$this->assertInstanceOf(BotCommandsInfo::class, $botCommands);
$this->assertCount(2, $botCommands->commands);
$this->assertInstanceOf(BotCommand::class, $botCommands->commands[0]);
$this->assertSame('start', $botCommands->commands[0]->name);
$this->assertNull($botCommands->commands[1]->description);
}

#[Test]
public function createBotInfoHandlesNullCommands(): void
{
Expand Down
48 changes: 48 additions & 0 deletions tests/Models/BotCommandsInfoTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace BushlanovDev\MaxMessengerBot\Tests\Models;

use BushlanovDev\MaxMessengerBot\Attributes\ArrayOf;
use BushlanovDev\MaxMessengerBot\Models\BotCommand;
use BushlanovDev\MaxMessengerBot\Models\BotCommandsInfo;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\UsesClass;
use PHPUnit\Framework\TestCase;

#[CoversClass(BotCommandsInfo::class)]
#[UsesClass(BotCommand::class)]
#[UsesClass(ArrayOf::class)]
final class BotCommandsInfoTest extends TestCase
{
#[Test]
public function canBeCreatedFromArray(): void
{
$info = BotCommandsInfo::fromArray([
'commands' => [
['name' => 'start', 'description' => 'Start the bot'],
],
]);

$this->assertCount(1, $info->commands);
$this->assertInstanceOf(BotCommand::class, $info->commands[0]);
$this->assertSame('start', $info->commands[0]->name);
$this->assertSame('Start the bot', $info->commands[0]->description);
}

#[Test]
public function commandsAreNullWhenTheBotHasNone(): void
{
$this->assertNull(BotCommandsInfo::fromArray([])->commands);
}

#[Test]
public function toArraySerializesCommands(): void
{
$info = new BotCommandsInfo([new BotCommand('help', 'Help')]);

$this->assertSame(['commands' => [['name' => 'help', 'description' => 'Help']]], $info->toArray());
}
}
Loading