From 8b752858a163c6dc74654d0a0da4fd7703dfe410 Mon Sep 17 00:00:00 2001 From: bernard-ng Date: Tue, 30 Jul 2024 02:26:24 +0200 Subject: [PATCH] feat: #465 add full reactions support as defined in api 7.0 --- CHANGELOG.md | 3 + src/BaseType.php | 3 +- src/BotApi.php | 26 +++++++ src/Types/ArrayOfReactionType.php | 2 +- src/Types/Update.php | 55 +++++++++++++++ tests/Types/ArrayOfReactionTypeTest.php | 40 +++++++++++ .../Types/MessageReactionCountUpdatedTest.php | 55 +++++++++++++++ tests/Types/MessageReactionUpdatedTest.php | 68 +++++++++++++++++++ tests/Types/UpdateTest.php | 8 +++ 9 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 tests/Types/ArrayOfReactionTypeTest.php create mode 100644 tests/Types/MessageReactionCountUpdatedTest.php create mode 100644 tests/Types/MessageReactionUpdatedTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d24ae09..c5395917 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ All Notable changes to `PHP Telegram Bot Api` will be documented in this file - Add method `\TelegramBot\Api\BotApi::validateWebAppData` to validate `window.Telegram.WebApp.initData` - Add `\TelegramBot\Api\Types\Message::$videoNote` field - Drop php < 8.1 +- Add `\TelegramBot\Api\Types\Update::$messageReaction` field +- Add `\TelegramBot\Api\Types\Update::$messageReactionCount` field +- Add `\TelegramBot\Api\BotApi::setMessageReaction` api method ## 2.5.0 - 2023-08-09 diff --git a/src/BaseType.php b/src/BaseType.php index f02e0eca..36d89a02 100644 --- a/src/BaseType.php +++ b/src/BaseType.php @@ -39,7 +39,8 @@ public static function validate($data) return true; } - throw new InvalidArgumentException(); + $missingParams = implode(', ', array_diff(static::$requiredParams, array_keys($data))); + throw new InvalidArgumentException(sprintf("Validation failed. Missing required parameters: %s", $missingParams)); } /** diff --git a/src/BotApi.php b/src/BotApi.php index 6e5fd307..d985fdd9 100644 --- a/src/BotApi.php +++ b/src/BotApi.php @@ -5,6 +5,7 @@ use TelegramBot\Api\Http\CurlHttpClient; use TelegramBot\Api\Http\HttpClientInterface; use TelegramBot\Api\Types\ArrayOfBotCommand; +use TelegramBot\Api\Types\ArrayOfReactionType; use TelegramBot\Api\Types\ArrayOfChatMemberEntity; use TelegramBot\Api\Types\ArrayOfMessageEntity; use TelegramBot\Api\Types\ArrayOfMessages; @@ -2771,6 +2772,31 @@ public function setProxy($proxyString = '', $socks5 = false) return $this; } + /** + * Use this method to change the chosen reactions on a message. + * Service messages can't be reacted to. + * Automatically forwarded messages from a channel to its discussion group have the same available reactions as messages in the channel. + * + * @param string|int $chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param int $messageId Identifier of the target message. + * @param ArrayOfReactionType $reaction A list of reaction types to set on the message. + * @param bool $isBig Pass `true` to set the reaction with a big animation + * + * @return bool + * @throws Exception + * + * @author bernard-ng + */ + public function setMessageReaction($chatId, $messageId, $reaction, $isBig = false) + { + return $this->call('setMessageReaction', [ + 'chat_id' => $chatId, + 'message_id' => $messageId, + 'reaction' => $reaction, + 'is_big' => $isBig + ]); + } + /** * Set an option for a cURL transfer * diff --git a/src/Types/ArrayOfReactionType.php b/src/Types/ArrayOfReactionType.php index afc13ecd..48fc3177 100644 --- a/src/Types/ArrayOfReactionType.php +++ b/src/Types/ArrayOfReactionType.php @@ -15,7 +15,7 @@ public static function fromResponse($data) { $arrayOfReactionTypes = []; foreach ($data as $reactionTypeData) { - // В зависимости от типа реакции, создаем соответствующий объект + // Depending on the type of reaction, create an appropriate object if ($reactionTypeData['type'] === 'emoji') { $arrayOfReactionTypes[] = ReactionTypeEmoji::fromResponse($reactionTypeData); } elseif ($reactionTypeData['type'] === 'custom_emoji') { diff --git a/src/Types/Update.php b/src/Types/Update.php index 4138ed07..77ea5f69 100644 --- a/src/Types/Update.php +++ b/src/Types/Update.php @@ -46,6 +46,8 @@ class Update extends BaseType implements TypeInterface 'my_chat_member' => ChatMemberUpdated::class, 'chat_member' => ChatMemberUpdated::class, 'chat_join_request' => ChatJoinRequest::class, + 'message_reaction' => MessageReactionUpdated::class, + 'message_reaction_count' => MessageReactionCountUpdated::class ]; /** @@ -159,6 +161,25 @@ class Update extends BaseType implements TypeInterface */ protected $chatJoinRequest; + /** + * Optional. A reaction to a message was changed by a user. + * The bot must be an administrator in the chat and must explicitly specify 'message_reaction' + * in the list of allowed_updates to receive these updates. The update isn't received for reactions set by bots. + * + * @var MessageReactionUpdated|null + */ + protected $messageReaction; + + /** + * Optional. Reactions to a message with anonymous reactions were changed. + * The bot must be an administrator in the chat and must explicitly specify 'message_reaction_count' + * in the list of allowed_updates to receive these updates. + * The updates are grouped and can be sent with delay up to a few minutes. + * + * @var MessageReactionCountUpdated|null + */ + protected $messageReactionCount; + /** * @return int */ @@ -433,4 +454,38 @@ public function setChatJoinRequest($chatJoinRequest) { $this->chatJoinRequest = $chatJoinRequest; } + + /** + * @return MessageReactionUpdated|null + */ + public function getMessageReaction() + { + return $this->messageReaction; + } + + /** + * @param MessageReactionUpdated|null $messageReaction + * @return void + */ + public function setMessageReaction(?MessageReactionUpdated $messageReaction) + { + $this->messageReaction = $messageReaction; + } + + /** + * @return MessageReactionCountUpdated|null + */ + public function getMessageReactionCount() + { + return $this->messageReactionCount; + } + + /** + * @param MessageReactionCountUpdated|null $messageReactionCount + * @return void + */ + public function setMessageReactionCount(?MessageReactionCountUpdated $messageReactionCount) + { + $this->messageReactionCount = $messageReactionCount; + } } diff --git a/tests/Types/ArrayOfReactionTypeTest.php b/tests/Types/ArrayOfReactionTypeTest.php new file mode 100644 index 00000000..8d84054c --- /dev/null +++ b/tests/Types/ArrayOfReactionTypeTest.php @@ -0,0 +1,40 @@ + '👍', + 'type' => 'emoji' + ], + [ + 'custom_emoji_id' => 'custom_emoji_123', + 'type' => 'custom_emoji' + ] + ]); + + $expected = [ + ReactionTypeEmoji::fromResponse([ + 'emoji' => '👍', + 'type' => 'emoji' + ]), + ReactionTypeCustomEmoji::fromResponse([ + 'custom_emoji_id' => 'custom_emoji_123', + 'type' => 'custom_emoji' + ]) + ]; + + foreach ($items as $key => $item) { + $this->assertEquals($expected[$key], $item); + } + } +} diff --git a/tests/Types/MessageReactionCountUpdatedTest.php b/tests/Types/MessageReactionCountUpdatedTest.php new file mode 100644 index 00000000..e69008ec --- /dev/null +++ b/tests/Types/MessageReactionCountUpdatedTest.php @@ -0,0 +1,55 @@ + ChatTest::getMinResponse(), + 'message_id' => 1, + 'date' => 1682343644, + 'reactions' => [ + ReactionTypeEmojiTest::getMinResponse() + ] + ]; + } + + public static function getFullResponse() + { + return [ + 'chat' => ChatTest::getFullResponse(), + 'message_id' => 1, + 'date' => 1682343644, + 'reactions' => [ + ReactionTypeEmojiTest::getFullResponse() + ] + ]; + } + + + protected function assertMinItem($item) + { + $this->assertEquals(ChatTest::createMinInstance(), $item->getChat()); + $this->assertEquals(1, $item->getMessageId()); + $this->assertEquals(1682343644, $item->getDate()); + $this->assertEquals([ReactionTypeEmojiTest::createMinInstance()], $item->getReactions()); + } + + protected function assertFullItem($item) + { + $this->assertEquals(ChatTest::createFullInstance(), $item->getChat()); + $this->assertEquals(1, $item->getMessageId()); + $this->assertEquals(1682343644, $item->getDate()); + $this->assertEquals([ReactionTypeEmojiTest::createFullInstance()], $item->getReactions()); + } +} diff --git a/tests/Types/MessageReactionUpdatedTest.php b/tests/Types/MessageReactionUpdatedTest.php new file mode 100644 index 00000000..02a48454 --- /dev/null +++ b/tests/Types/MessageReactionUpdatedTest.php @@ -0,0 +1,68 @@ + ChatTest::getMinResponse(), + 'message_id' => 1, + 'date' => 1682343644, + 'old_reaction' => [ + ReactionTypeEmojiTest::getMinResponse() + ], + 'new_reaction' => [ + ReactionTypeCustomEmojiTest::getMinResponse() + ] + ]; + } + + public static function getFullResponse() + { + return [ + 'chat' => ChatTest::getMinResponse(), + 'message_id' => 1, + 'user' => UserTest::getMinResponse(), + 'actor_chat' => ChatTest::getMinResponse(), + 'date' => 1682343644, + 'old_reaction' => [ + ReactionTypeEmojiTest::getMinResponse() + ], + 'new_reaction' => [ + ReactionTypeCustomEmojiTest::getMinResponse() + ] + ]; + } + + protected function assertMinItem($item) + { + $this->assertEquals(ChatTest::createMinInstance(), $item->getChat()); + $this->assertEquals(1, $item->getMessageId()); + $this->assertEquals(1682343644, $item->getDate()); + $this->assertEquals([ReactionTypeEmojiTest::createMinInstance()], $item->getOldReaction()); + $this->assertEquals([ReactionTypeCustomEmojiTest::createMinInstance()],$item->getNewReaction()); + + $this->assertNull($item->getUser()); + $this->assertNull($item->getActorChat()); + } + + protected function assertFullItem($item) + { + $this->assertEquals(ChatTest::createMinInstance(), $item->getChat()); + $this->assertEquals(1, $item->getMessageId()); + $this->assertEquals(UserTest::createMinInstance(), $item->getUser()); + $this->assertEquals(ChatTest::createMinInstance(), $item->getActorChat()); + $this->assertEquals([ReactionTypeEmojiTest::createMinInstance()], $item->getOldReaction()); + $this->assertEquals([ReactionTypeCustomEmojiTest::createMinInstance()],$item->getNewReaction()); + } +} diff --git a/tests/Types/UpdateTest.php b/tests/Types/UpdateTest.php index 0af8523a..d91f7563 100644 --- a/tests/Types/UpdateTest.php +++ b/tests/Types/UpdateTest.php @@ -3,6 +3,8 @@ namespace TelegramBot\Api\Test\Types; use TelegramBot\Api\Test\AbstractTypeTest; +use TelegramBot\Api\Types\MessageReactionUpdated; +use TelegramBot\Api\Types\MessageReactionCountUpdated; use TelegramBot\Api\Test\Types\Inline\ChosenInlineResultTest; use TelegramBot\Api\Test\Types\Inline\InlineQueryTest; use TelegramBot\Api\Test\Types\Payments\Query\PreCheckoutQueryTest; @@ -39,6 +41,8 @@ public static function getFullResponse() 'poll_answer' => PollAnswerTest::getMinResponse(), 'poll' => PollTest::getMinResponse(), 'chat_join_request' => ChatJoinRequestTest::getMinResponse(), + 'message_reaction' => MessageReactionUpdatedTest::getMinResponse(), + 'message_reaction_count' => MessageReactionCountUpdatedTest::getMinResponse(), ]; } @@ -63,6 +67,8 @@ protected function assertMinItem($item) $this->assertNull($item->getMyChatMember()); $this->assertNull($item->getChatMember()); $this->assertNull($item->getChatJoinRequest()); + $this->assertNull($item->getMessageReaction()); + $this->assertNull($item->getMessageReactionCount()); } /** @@ -84,5 +90,7 @@ protected function assertFullItem($item) $this->assertEquals(PollAnswerTest::createMinInstance(), $item->getPollAnswer()); $this->assertEquals(PollTest::createMinInstance(), $item->getPoll()); $this->assertEquals(ChatJoinRequestTest::createMinInstance(), $item->getChatJoinRequest()); + $this->assertEquals(MessageReactionUpdatedTest::createMinInstance(), $item->getMessageReaction()); + $this->assertEquals(MessageReactionCountUpdatedTest::createMinInstance(), $item->getMessageReactionCount()); } }