diff --git a/CHANGELOG.md b/CHANGELOG.md index 48edf35d..353f8e8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Telegram Bot API for PHP Change Log +## 0.14.1 February 9, 2026 + +- New #186: Add `SetMyProfilePhoto`, `RemoveMyProfilePhoto` and `GetUserProfileAudios` methods. +- New #186: Add `ChatOwnerLeft`, `ChatOwnerChanged`, `VideoQuality` and `UserProfileAudios` types. +- New #186: Add `allowsUsersToCreateTopics` field to `User` type. +- New #186: Add `iconCustomEmojiId` and `style` fields to `KeyboardButton` type. +- New #186: Add `iconCustomEmojiId` and `style` fields to `InlineKeyboardButton` type. +- New #186: Add `chatOwnerLeft` and `chatOwnerChanged` fields to `Message` type. +- New #186: Add `qualities` field to `Video` type. +- New #186: Add `firstProfileAudio` field to `ChatFullInfo` type. +- New #186: Add `rarity` field to `UniqueGiftModel` type. +- New #186: Add `isBurned` field to `UniqueGift` type. + ## 0.14 February 7, 2026 - New #182: Introduce resource readers that handle reading content from different types of resources stored in diff --git a/README.md b/README.md index b2e10e60..0c87c786 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ The package provides a simple and convenient way to interact with the Telegram Bot API. -✔️ Telegram Bot API 9.3 (December 31, 2025) is **fully supported**. +✔️ Telegram Bot API 9.4 (February 9, 2026) is **fully supported**. > [!IMPORTANT] > This project is developed and maintained by [Sergei Predvoditelev](https://github.com/vjik). diff --git a/src/Method/GetUserProfileAudios.php b/src/Method/GetUserProfileAudios.php new file mode 100644 index 00000000..b84b0e1e --- /dev/null +++ b/src/Method/GetUserProfileAudios.php @@ -0,0 +1,51 @@ + + */ +final readonly class GetUserProfileAudios implements MethodInterface +{ + public function __construct( + private int $userId, + private ?int $offset = null, + private ?int $limit = null, + ) {} + + public function getHttpMethod(): HttpMethod + { + return HttpMethod::GET; + } + + public function getApiMethod(): string + { + return 'getUserProfileAudios'; + } + + public function getData(): array + { + return array_filter( + [ + 'user_id' => $this->userId, + 'offset' => $this->offset, + 'limit' => $this->limit, + ], + static fn(mixed $value): bool => $value !== null, + ); + } + + public function getResultType(): ObjectValue + { + return new ObjectValue(UserProfileAudios::class); + } +} diff --git a/src/Method/RemoveMyProfilePhoto.php b/src/Method/RemoveMyProfilePhoto.php new file mode 100644 index 00000000..95afed2e --- /dev/null +++ b/src/Method/RemoveMyProfilePhoto.php @@ -0,0 +1,39 @@ + + * + * @api + */ +final readonly class RemoveMyProfilePhoto implements MethodInterface +{ + public function getHttpMethod(): HttpMethod + { + return HttpMethod::POST; + } + + public function getApiMethod(): string + { + return 'removeMyProfilePhoto'; + } + + public function getData(): array + { + return []; + } + + public function getResultType(): TrueValue + { + return new TrueValue(); + } +} diff --git a/src/Method/SetMyProfilePhoto.php b/src/Method/SetMyProfilePhoto.php new file mode 100644 index 00000000..477b00d3 --- /dev/null +++ b/src/Method/SetMyProfilePhoto.php @@ -0,0 +1,51 @@ + + * + * @api + */ +final readonly class SetMyProfilePhoto implements MethodInterface +{ + public function __construct( + private InputProfilePhoto $photo, + ) {} + + public function getHttpMethod(): HttpMethod + { + return HttpMethod::POST; + } + + public function getApiMethod(): string + { + return 'setMyProfilePhoto'; + } + + public function getData(): array + { + $fileCollector = new FileCollector(); + $photo = $this->photo->toRequestArray($fileCollector); + + return [ + 'photo' => $photo, + ...$fileCollector->get(), + ]; + } + + public function getResultType(): TrueValue + { + return new TrueValue(); + } +} diff --git a/src/TelegramBotApi.php b/src/TelegramBotApi.php index 4023f102..2ebac77d 100644 --- a/src/TelegramBotApi.php +++ b/src/TelegramBotApi.php @@ -61,6 +61,7 @@ use Phptg\BotApi\Method\GetMyStarBalance; use Phptg\BotApi\Method\GetUserChatBoosts; use Phptg\BotApi\Method\GetUserGifts; +use Phptg\BotApi\Method\GetUserProfileAudios; use Phptg\BotApi\Method\GetUserProfilePhotos; use Phptg\BotApi\Method\GiftPremiumSubscription; use Phptg\BotApi\Method\HideGeneralForumTopic; @@ -82,6 +83,7 @@ use Phptg\BotApi\Method\PromoteChatMember; use Phptg\BotApi\Method\RepostStory; use Phptg\BotApi\Method\RemoveBusinessAccountProfilePhoto; +use Phptg\BotApi\Method\RemoveMyProfilePhoto; use Phptg\BotApi\Method\RemoveChatVerification; use Phptg\BotApi\Method\RemoveUserVerification; use Phptg\BotApi\Method\ReopenForumTopic; @@ -123,6 +125,7 @@ use Phptg\BotApi\Method\SetMyDefaultAdministratorRights; use Phptg\BotApi\Method\SetMyDescription; use Phptg\BotApi\Method\SetMyName; +use Phptg\BotApi\Method\SetMyProfilePhoto; use Phptg\BotApi\Method\SetMyShortDescription; use Phptg\BotApi\Method\SetUserEmojiStatus; use Phptg\BotApi\Method\Sticker\AddStickerToSet; @@ -236,6 +239,7 @@ use Phptg\BotApi\Type\Update\WebhookInfo; use Phptg\BotApi\Type\User; use Phptg\BotApi\Type\UserChatBoosts; +use Phptg\BotApi\Type\UserProfileAudios; use Phptg\BotApi\Type\UserProfilePhotos; use function extension_loaded; @@ -1459,6 +1463,19 @@ public function getUserGifts( ); } + /** + * @see https://core.telegram.org/bots/api#getuserprofileaudios + */ + public function getUserProfileAudios( + int $userId, + ?int $offset = null, + ?int $limit = null, + ): FailResult|UserProfileAudios { + return $this->call( + new GetUserProfileAudios($userId, $offset, $limit), + ); + } + /** * @see https://core.telegram.org/bots/api#getuserprofilephotos */ @@ -1683,6 +1700,14 @@ public function removeBusinessAccountProfilePhoto( ); } + /** + * @see https://core.telegram.org/bots/api#removemyprofilephoto + */ + public function removeMyProfilePhoto(): FailResult|true + { + return $this->call(new RemoveMyProfilePhoto()); + } + /** * @see https://core.telegram.org/bots/api#removechatverification */ @@ -2956,6 +2981,14 @@ public function setMyName(?string $name = null, ?string $languageCode = null): F return $this->call(new SetMyName($name, $languageCode)); } + /** + * @see https://core.telegram.org/bots/api#setmyprofilephoto + */ + public function setMyProfilePhoto(InputProfilePhoto $photo): FailResult|true + { + return $this->call(new SetMyProfilePhoto($photo)); + } + /** * @see https://core.telegram.org/bots/api#setmyshortdescription */ diff --git a/src/Type/ChatFullInfo.php b/src/Type/ChatFullInfo.php index 8d1af0b1..a1bf69d8 100644 --- a/src/Type/ChatFullInfo.php +++ b/src/Type/ChatFullInfo.php @@ -73,5 +73,6 @@ public function __construct( public ?UserRating $rating = null, public ?UniqueGiftColors $uniqueGiftColors = null, public ?int $paidMessageStarCount = null, + public ?Audio $firstProfileAudio = null, ) {} } diff --git a/src/Type/ChatOwnerChanged.php b/src/Type/ChatOwnerChanged.php new file mode 100644 index 00000000..afcc134e --- /dev/null +++ b/src/Type/ChatOwnerChanged.php @@ -0,0 +1,17 @@ + $this->text, + 'icon_custom_emoji_id' => $this->iconCustomEmojiId, + 'style' => $this->style, 'url' => $this->url, 'callback_data' => $this->callbackData, 'web_app' => $this->webApp?->toRequestArray(), diff --git a/src/Type/KeyboardButton.php b/src/Type/KeyboardButton.php index 89a0e25b..3e4ce7a3 100644 --- a/src/Type/KeyboardButton.php +++ b/src/Type/KeyboardButton.php @@ -19,6 +19,8 @@ public function __construct( public ?bool $requestLocation = null, public ?KeyboardButtonPollType $requestPoll = null, public ?WebAppInfo $webApp = null, + public ?string $iconCustomEmojiId = null, + public ?string $style = null, ) {} public function toRequestArray(): array @@ -26,6 +28,8 @@ public function toRequestArray(): array return array_filter( [ 'text' => $this->text, + 'icon_custom_emoji_id' => $this->iconCustomEmojiId, + 'style' => $this->style, 'request_users' => $this->requestUsers?->toRequestArray(), 'request_chat' => $this->requestChat?->toRequestArray(), 'request_contact' => $this->requestContact, diff --git a/src/Type/Message.php b/src/Type/Message.php index 6d5cc080..3273a833 100644 --- a/src/Type/Message.php +++ b/src/Type/Message.php @@ -138,5 +138,7 @@ public function __construct( public ?SuggestedPostDeclined $suggestedPostDeclined = null, public ?SuggestedPostPaid $suggestedPostPaid = null, public ?SuggestedPostRefunded $suggestedPostRefunded = null, + public ?ChatOwnerLeft $chatOwnerLeft = null, + public ?ChatOwnerChanged $chatOwnerChanged = null, ) {} } diff --git a/src/Type/UniqueGift.php b/src/Type/UniqueGift.php index e78ce96c..def6df2f 100644 --- a/src/Type/UniqueGift.php +++ b/src/Type/UniqueGift.php @@ -23,5 +23,6 @@ public function __construct( public ?true $isFromBlockchain = null, public ?UniqueGiftColors $colors = null, public ?Chat $publisherChat = null, + public ?true $isBurned = null, ) {} } diff --git a/src/Type/UniqueGiftModel.php b/src/Type/UniqueGiftModel.php index 28cef407..21ece9dd 100644 --- a/src/Type/UniqueGiftModel.php +++ b/src/Type/UniqueGiftModel.php @@ -17,5 +17,6 @@ public function __construct( public string $name, public Sticker $sticker, public int $rarityPerMille, + public ?string $rarity = null, ) {} } diff --git a/src/Type/User.php b/src/Type/User.php index b1f2394a..d4cdcc6b 100644 --- a/src/Type/User.php +++ b/src/Type/User.php @@ -26,6 +26,7 @@ public function __construct( public ?bool $canConnectToBusiness = null, public ?bool $hasMainWebApp = null, public ?bool $hasTopicsEnabled = null, + public ?bool $allowsUsersToCreateTopics = null, ) {} public function toRequestArray(): array @@ -46,6 +47,7 @@ public function toRequestArray(): array 'can_connect_to_business' => $this->canConnectToBusiness, 'has_main_web_app' => $this->hasMainWebApp, 'has_topics_enabled' => $this->hasTopicsEnabled, + 'allows_users_to_create_topics' => $this->allowsUsersToCreateTopics, ], static fn(mixed $value): bool => $value !== null, ); diff --git a/src/Type/UserProfileAudios.php b/src/Type/UserProfileAudios.php new file mode 100644 index 00000000..5c39c5ef --- /dev/null +++ b/src/Type/UserProfileAudios.php @@ -0,0 +1,24 @@ +getHttpMethod()); + assertSame('getUserProfileAudios', $method->getApiMethod()); + assertSame( + [ + 'user_id' => 123, + ], + $method->getData(), + ); + } + + public function testFull(): void + { + $method = new GetUserProfileAudios( + 123, + 1, + 2, + ); + + assertSame( + [ + 'user_id' => 123, + 'offset' => 1, + 'limit' => 2, + ], + $method->getData(), + ); + } + + public function testPrepareResult(): void + { + $method = new GetUserProfileAudios(123); + + $preparedResult = TestHelper::createSuccessStubApi([ + 'total_count' => 1, + 'audios' => [ + [ + 'file_id' => 'file_id', + 'file_unique_id' => 'file_unique_id', + 'duration' => 120, + 'performer' => 'performer', + 'title' => 'title', + ], + ], + ])->call($method); + + assertSame(1, $preparedResult->totalCount); + assertCount(1, $preparedResult->audios); + assertSame('file_id', $preparedResult->audios[0]->fileId); + } +} diff --git a/tests/Method/RemoveMyProfilePhotoTest.php b/tests/Method/RemoveMyProfilePhotoTest.php new file mode 100644 index 00000000..9063522a --- /dev/null +++ b/tests/Method/RemoveMyProfilePhotoTest.php @@ -0,0 +1,34 @@ +getHttpMethod()); + assertSame('removeMyProfilePhoto', $method->getApiMethod()); + assertSame([], $method->getData()); + } + + public function testPrepareResult(): void + { + $method = new RemoveMyProfilePhoto(); + + $preparedResult = TestHelper::createSuccessStubApi(true)->call($method); + + assertTrue($preparedResult); + } +} diff --git a/tests/Method/SetMyProfilePhotoTest.php b/tests/Method/SetMyProfilePhotoTest.php new file mode 100644 index 00000000..17f7197d --- /dev/null +++ b/tests/Method/SetMyProfilePhotoTest.php @@ -0,0 +1,48 @@ +createStream()); + $photo = new InputProfilePhotoStatic($file); + $method = new SetMyProfilePhoto($photo); + + assertSame(HttpMethod::POST, $method->getHttpMethod()); + assertSame('setMyProfilePhoto', $method->getApiMethod()); + assertSame( + [ + 'photo' => $photo->toRequestArray(new FileCollector()), + 'file0' => $file, + ], + $method->getData(), + ); + } + + public function testPrepareResult(): void + { + $file = new InputFile((new StreamFactory())->createStream()); + $photo = new InputProfilePhotoStatic($file); + $method = new SetMyProfilePhoto($photo); + + $preparedResult = TestHelper::createSuccessStubApi(true)->call($method); + + assertTrue($preparedResult); + } +} diff --git a/tests/TelegramBotApiTest.php b/tests/TelegramBotApiTest.php index c24324eb..88f0cdaa 100644 --- a/tests/TelegramBotApiTest.php +++ b/tests/TelegramBotApiTest.php @@ -53,6 +53,7 @@ use Phptg\BotApi\Type\Story; use Phptg\BotApi\Type\User; use Phptg\BotApi\Type\UserChatBoosts; +use Phptg\BotApi\Type\UserProfileAudios; use Phptg\BotApi\Type\UserProfilePhotos; use Phptg\BotApi\Type\Update\Update; use Phptg\BotApi\Type\Update\WebhookInfo; @@ -1518,6 +1519,18 @@ public function testGetUserGifts(): void assertInstanceOf(OwnedGifts::class, $result); } + public function testGetUserProfileAudios(): void + { + $api = TestHelper::createSuccessStubApi([ + 'total_count' => 0, + 'audios' => [], + ]); + + $result = $api->getUserProfileAudios(7); + + assertInstanceOf(UserProfileAudios::class, $result); + } + public function testGetUserProfilePhotos(): void { $api = TestHelper::createSuccessStubApi([ @@ -1676,6 +1689,15 @@ public function testRemoveBusinessAccountProfilePhoto(): void assertTrue($result); } + public function testRemoveMyProfilePhoto(): void + { + $api = TestHelper::createSuccessStubApi(true); + + $result = $api->removeMyProfilePhoto(); + + assertTrue($result); + } + public function testRemoveChatVerification(): void { $api = TestHelper::createSuccessStubApi(true); @@ -2312,6 +2334,19 @@ public function testSetMyName(): void assertTrue($result); } + public function testSetMyProfilePhoto(): void + { + $api = TestHelper::createSuccessStubApi(true); + + $result = $api->setMyProfilePhoto( + new InputProfilePhotoStatic( + new InputFile((new StreamFactory())->createStream()), + ), + ); + + assertTrue($result); + } + public function testSetMyShortDescription(): void { $api = TestHelper::createSuccessStubApi(true); diff --git a/tests/Type/ChatFullInfoTest.php b/tests/Type/ChatFullInfoTest.php index 9e2403c2..f5c5f8f4 100644 --- a/tests/Type/ChatFullInfoTest.php +++ b/tests/Type/ChatFullInfoTest.php @@ -18,6 +18,7 @@ use Phptg\BotApi\Type\ChatPhoto; use Phptg\BotApi\Type\Message; use Phptg\BotApi\Type\ReactionTypeCustomEmoji; +use Phptg\BotApi\Type\Audio; use Phptg\BotApi\Type\UniqueGiftColors; use Phptg\BotApi\Type\UserRating; @@ -85,6 +86,7 @@ public function testBase(): void assertNull($info->rating); assertNull($info->uniqueGiftColors); assertNull($info->paidMessageStarCount); + assertNull($info->firstProfileAudio); } public function testFromTelegramResult(): void @@ -195,6 +197,13 @@ public function testFromTelegramResult(): void 'current_level_rating' => 800, 'next_level_rating' => 1200, ], + 'first_profile_audio' => [ + 'file_id' => 'audio_f1', + 'file_unique_id' => 'audio_fu1', + 'duration' => 180, + 'performer' => 'Artist', + 'title' => 'Song', + ], 'unique_gift_colors' => [ 'model_custom_emoji_id' => 'model_emoji_123', 'symbol_custom_emoji_id' => 'symbol_emoji_456', @@ -299,5 +308,11 @@ public function testFromTelegramResult(): void assertSame([0x2A2A2A, 0x3A3A3A], $info->uniqueGiftColors->darkThemeOtherColors); assertSame(100, $info->paidMessageStarCount); + + assertInstanceOf(Audio::class, $info->firstProfileAudio); + assertSame('audio_f1', $info->firstProfileAudio->fileId); + assertSame(180, $info->firstProfileAudio->duration); + assertSame('Artist', $info->firstProfileAudio->performer); + assertSame('Song', $info->firstProfileAudio->title); } } diff --git a/tests/Type/ChatOwnerChangedTest.php b/tests/Type/ChatOwnerChangedTest.php new file mode 100644 index 00000000..0748d5fa --- /dev/null +++ b/tests/Type/ChatOwnerChangedTest.php @@ -0,0 +1,38 @@ +newOwner); + } + + public function testFromTelegramResult(): void + { + $chatOwnerChanged = (new ObjectFactory())->create([ + 'new_owner' => [ + 'id' => 1, + 'is_bot' => false, + 'first_name' => 'Sergei', + ], + ], null, ChatOwnerChanged::class); + + assertInstanceOf(User::class, $chatOwnerChanged->newOwner); + assertSame(1, $chatOwnerChanged->newOwner->id); + } +} diff --git a/tests/Type/ChatOwnerLeftTest.php b/tests/Type/ChatOwnerLeftTest.php new file mode 100644 index 00000000..ade9b1eb --- /dev/null +++ b/tests/Type/ChatOwnerLeftTest.php @@ -0,0 +1,46 @@ +newOwner); + } + + public function testFull(): void + { + $newOwner = new User(1, false, 'Sergei'); + $chatOwnerLeft = new ChatOwnerLeft($newOwner); + + assertSame($newOwner, $chatOwnerLeft->newOwner); + } + + public function testFromTelegramResult(): void + { + $chatOwnerLeft = (new ObjectFactory())->create([ + 'new_owner' => [ + 'id' => 1, + 'is_bot' => false, + 'first_name' => 'Sergei', + ], + ], null, ChatOwnerLeft::class); + + assertInstanceOf(User::class, $chatOwnerLeft->newOwner); + assertSame(1, $chatOwnerLeft->newOwner->id); + } +} diff --git a/tests/Type/InlineKeyboardButtonTest.php b/tests/Type/InlineKeyboardButtonTest.php index 6881db6a..fee9733b 100644 --- a/tests/Type/InlineKeyboardButtonTest.php +++ b/tests/Type/InlineKeyboardButtonTest.php @@ -25,6 +25,8 @@ public function testBase(): void $button = new InlineKeyboardButton('test'); assertSame('test', $button->text); + assertNull($button->iconCustomEmojiId); + assertNull($button->style); assertNull($button->url); assertNull($button->callbackData); assertNull($button->webApp); @@ -63,9 +65,13 @@ public function testFilled(): void $callbackGame, true, $copyText, + '5368324170671202286', + 'primary', ); assertSame('test', $button->text); + assertSame('5368324170671202286', $button->iconCustomEmojiId); + assertSame('primary', $button->style); assertSame('https://example.com', $button->url); assertSame('callback-data', $button->callbackData); assertSame($webApp, $button->webApp); @@ -80,6 +86,8 @@ public function testFilled(): void assertSame( [ 'text' => 'test', + 'icon_custom_emoji_id' => '5368324170671202286', + 'style' => 'primary', 'url' => 'https://example.com', 'callback_data' => 'callback-data', 'web_app' => $webApp->toRequestArray(), @@ -99,6 +107,8 @@ public function testFromTelegramResult(): void { $button = (new ObjectFactory())->create([ 'text' => 'test', + 'icon_custom_emoji_id' => '5368324170671202286', + 'style' => 'primary', 'url' => 'https://example.com', 'callback_data' => 'callback-data', 'web_app' => ['url' => 'https://example.com/test'], @@ -112,6 +122,8 @@ public function testFromTelegramResult(): void ], null, InlineKeyboardButton::class); assertSame('test', $button->text); + assertSame('5368324170671202286', $button->iconCustomEmojiId); + assertSame('primary', $button->style); assertSame('https://example.com', $button->url); assertSame('callback-data', $button->callbackData); assertSame('https://example.com/test', $button->webApp?->url); diff --git a/tests/Type/KeyboardButtonTest.php b/tests/Type/KeyboardButtonTest.php index 6cbb0b5b..a0404803 100644 --- a/tests/Type/KeyboardButtonTest.php +++ b/tests/Type/KeyboardButtonTest.php @@ -23,6 +23,8 @@ public function testBase(): void $button = new KeyboardButton('test'); assertSame('test', $button->text); + assertNull($button->iconCustomEmojiId); + assertNull($button->style); assertNull($button->requestUsers); assertNull($button->requestChat); assertNull($button->requestContact); @@ -52,9 +54,13 @@ public function testFilled(): void false, $requestPoll, $webApp, + '5368324170671202286', + 'primary', ); assertSame('test', $button->text); + assertSame('5368324170671202286', $button->iconCustomEmojiId); + assertSame('primary', $button->style); assertSame($requestUsers, $button->requestUsers); assertSame($requestChat, $button->requestChat); assertTrue($button->requestContact); @@ -65,6 +71,8 @@ public function testFilled(): void assertSame( [ 'text' => 'test', + 'icon_custom_emoji_id' => '5368324170671202286', + 'style' => 'primary', 'request_users' => $requestUsers->toRequestArray(), 'request_chat' => $requestChat->toRequestArray(), 'request_contact' => true, diff --git a/tests/Type/MessageTest.php b/tests/Type/MessageTest.php index 12b984a1..cd0ab88e 100644 --- a/tests/Type/MessageTest.php +++ b/tests/Type/MessageTest.php @@ -143,6 +143,8 @@ public function testBase(): void assertNull($message->suggestedPostDeclined); assertNull($message->suggestedPostPaid); assertNull($message->suggestedPostRefunded); + assertNull($message->chatOwnerLeft); + assertNull($message->chatOwnerChanged); } public function testFromTelegramResult(): void @@ -633,6 +635,20 @@ public function testFromTelegramResult(): void ['id' => 4, 'text' => 'Task 4'], ], ], + 'chat_owner_left' => [ + 'new_owner' => [ + 'id' => 800, + 'is_bot' => false, + 'first_name' => 'Sergei', + ], + ], + 'chat_owner_changed' => [ + 'new_owner' => [ + 'id' => 801, + 'is_bot' => false, + 'first_name' => 'Ivan', + ], + ], ], null, Message::class); assertSame(7, $message->messageId); @@ -771,5 +787,7 @@ public function testFromTelegramResult(): void assertSame('insufficient_funds', $message->suggestedPostDeclined?->comment); assertSame('RUB', $message->suggestedPostPaid?->currency); assertSame('refund_reason', $message->suggestedPostRefunded?->reason); + assertSame(800, $message->chatOwnerLeft?->newOwner?->id); + assertSame(801, $message->chatOwnerChanged?->newOwner->id); } } diff --git a/tests/Type/UniqueGiftModelTest.php b/tests/Type/UniqueGiftModelTest.php index 004731d4..0d34e90a 100644 --- a/tests/Type/UniqueGiftModelTest.php +++ b/tests/Type/UniqueGiftModelTest.php @@ -10,6 +10,7 @@ use Phptg\BotApi\Type\UniqueGiftModel; use function PHPUnit\Framework\assertInstanceOf; +use function PHPUnit\Framework\assertNull; use function PHPUnit\Framework\assertSame; final class UniqueGiftModelTest extends TestCase @@ -22,6 +23,18 @@ public function testBase(): void assertSame('modelId', $model->name); assertSame($sticker, $model->sticker); assertSame(500, $model->rarityPerMille); + assertNull($model->rarity); + } + + public function testFull(): void + { + $sticker = new Sticker('stickerId', 'uniqueStickerId', 'unique', 100, 120, false, true); + $model = new UniqueGiftModel('modelId', $sticker, 500, 'rare'); + + assertSame('modelId', $model->name); + assertSame($sticker, $model->sticker); + assertSame(500, $model->rarityPerMille); + assertSame('rare', $model->rarity); } public function testFromTelegramResult(): void @@ -38,11 +51,13 @@ public function testFromTelegramResult(): void 'is_video' => true, ], 'rarity_per_mille' => 500, + 'rarity' => 'epic', ], null, UniqueGiftModel::class); assertInstanceOf(UniqueGiftModel::class, $model); assertSame('modelId', $model->name); assertSame('stickerId', $model->sticker->fileId); assertSame(500, $model->rarityPerMille); + assertSame('epic', $model->rarity); } } diff --git a/tests/Type/UniqueGiftTest.php b/tests/Type/UniqueGiftTest.php index b10aa47a..958205d6 100644 --- a/tests/Type/UniqueGiftTest.php +++ b/tests/Type/UniqueGiftTest.php @@ -6,6 +6,7 @@ use PHPUnit\Framework\TestCase; use Phptg\BotApi\ParseResult\ObjectFactory; +use Phptg\BotApi\Type\Chat; use Phptg\BotApi\Type\Sticker\Sticker; use Phptg\BotApi\Type\UniqueGift; use Phptg\BotApi\Type\UniqueGiftBackdrop; @@ -51,6 +52,63 @@ public function testBase(): void assertNull($type->isFromBlockchain); assertNull($type->colors); assertNull($type->publisherChat); + assertNull($type->isBurned); + } + + public function testFull(): void + { + $model = new UniqueGiftModel( + 'modelId', + new Sticker('stickerId', 'uniqueStickerId', 'unique', 100, 120, false, true), + 500, + ); + $symbol = new UniqueGiftSymbol( + 'symbolId', + new Sticker('stickerId', 'uniqueStickerId', 'unique', 100, 120, false, true), + 300, + ); + $backdrop = new UniqueGiftBackdrop( + 'backdropId', + new UniqueGiftBackdropColors(1, 2, 3, 4), + 200, + ); + $colors = new UniqueGiftColors( + 'model-emoji-123', + 'symbol-emoji-456', + 16733525, + [13041721, 9473087], + 5773381, + [16761600, 14349222], + ); + $publisherChat = new Chat(789, 'channel'); + + $type = new UniqueGift( + 'gift123', + 'baseName', + 'uniqueName', + 1, + $model, + $symbol, + $backdrop, + true, + true, + $colors, + $publisherChat, + true, + ); + + assertSame('gift123', $type->giftId); + assertSame('baseName', $type->baseName); + assertSame('uniqueName', $type->name); + assertSame(1, $type->number); + assertSame($model, $type->model); + assertSame($symbol, $type->symbol); + assertSame($backdrop, $type->backdrop); + assertSame(true, $type->isPremium); + assertSame(true, $type->isFromBlockchain); + assertSame($colors, $type->colors); + assertSame($publisherChat, $type->publisherChat); + assertSame(true, $type->isBurned); } public function testFromTelegramResult(): void @@ -97,6 +155,7 @@ public function testFromTelegramResult(): void 'rarity_per_mille' => 200, ], 'is_premium' => true, + 'is_burned' => true, 'is_from_blockchain' => true, 'colors' => [ 'model_custom_emoji_id' => 'model-emoji-123', @@ -136,5 +195,6 @@ public function testFromTelegramResult(): void assertSame('symbol-emoji-456', $type->colors->symbolCustomEmojiId); assertSame(16733525, $type->colors->lightThemeMainColor); assertSame(789, $type->publisherChat?->id); + assertSame(true, $type->isBurned); } } diff --git a/tests/Type/UserProfileAudiosTest.php b/tests/Type/UserProfileAudiosTest.php new file mode 100644 index 00000000..0a443156 --- /dev/null +++ b/tests/Type/UserProfileAudiosTest.php @@ -0,0 +1,51 @@ +totalCount); + assertSame([], $userProfileAudios->audios); + } + + public function testFromTelegramResult(): void + { + $userProfileAudios = (new ObjectFactory())->create([ + 'total_count' => 2, + 'audios' => [ + [ + 'file_id' => 'audio_f1', + 'file_unique_id' => 'audio_fu1', + 'duration' => 180, + 'performer' => 'Artist 1', + 'title' => 'Song 1', + ], + [ + 'file_id' => 'audio_f2', + 'file_unique_id' => 'audio_fu2', + 'duration' => 240, + 'performer' => 'Artist 2', + 'title' => 'Song 2', + ], + ], + ], null, UserProfileAudios::class); + + assertSame(2, $userProfileAudios->totalCount); + assertCount(2, $userProfileAudios->audios); + assertSame('audio_f1', $userProfileAudios->audios[0]->fileId); + assertSame('audio_f2', $userProfileAudios->audios[1]->fileId); + } +} diff --git a/tests/Type/UserTest.php b/tests/Type/UserTest.php index 08b8a646..87939a05 100644 --- a/tests/Type/UserTest.php +++ b/tests/Type/UserTest.php @@ -32,6 +32,7 @@ public function testBase(): void assertNull($user->canConnectToBusiness); assertNull($user->hasMainWebApp); assertNull($user->hasTopicsEnabled); + assertNull($user->allowsUsersToCreateTopics); } public function testToRequestArray(): void @@ -51,6 +52,7 @@ public function testToRequestArray(): void true, false, true, + true, ); assertSame( @@ -69,6 +71,7 @@ public function testToRequestArray(): void 'can_connect_to_business' => true, 'has_main_web_app' => false, 'has_topics_enabled' => true, + 'allows_users_to_create_topics' => true, ], $user->toRequestArray(), ); @@ -91,6 +94,7 @@ public function testFromTelegramResult(): void 'can_connect_to_business' => true, 'has_main_web_app' => false, 'has_topics_enabled' => true, + 'allows_users_to_create_topics' => true, ], null, User::class); assertInstanceOf(User::class, $user); @@ -108,5 +112,6 @@ public function testFromTelegramResult(): void assertSame(true, $user->canConnectToBusiness); assertSame(false, $user->hasMainWebApp); assertSame(true, $user->hasTopicsEnabled); + assertSame(true, $user->allowsUsersToCreateTopics); } } diff --git a/tests/Type/VideoQualityTest.php b/tests/Type/VideoQualityTest.php new file mode 100644 index 00000000..edead511 --- /dev/null +++ b/tests/Type/VideoQualityTest.php @@ -0,0 +1,60 @@ +fileId); + assertSame('fileUniqueId', $videoQuality->fileUniqueId); + assertSame(1920, $videoQuality->width); + assertSame(1080, $videoQuality->height); + assertSame('h264', $videoQuality->codec); + assertNull($videoQuality->fileSize); + } + + public function testFull(): void + { + $videoQuality = new VideoQuality('fileId', 'fileUniqueId', 1920, 1080, 'h265', 4096); + + assertSame('fileId', $videoQuality->fileId); + assertSame('fileUniqueId', $videoQuality->fileUniqueId); + assertSame(1920, $videoQuality->width); + assertSame(1080, $videoQuality->height); + assertSame('h265', $videoQuality->codec); + assertSame(4096, $videoQuality->fileSize); + } + + public function testFromTelegramResult(): void + { + $videoQuality = (new ObjectFactory())->create([ + 'file_id' => 'fileId', + 'file_unique_id' => 'fileUniqueId', + 'width' => 1920, + 'height' => 1080, + 'codec' => 'h265', + 'file_size' => 4096, + ], null, VideoQuality::class); + + assertInstanceOf(VideoQuality::class, $videoQuality); + assertSame('fileId', $videoQuality->fileId); + assertSame('fileUniqueId', $videoQuality->fileUniqueId); + assertSame(1920, $videoQuality->width); + assertSame(1080, $videoQuality->height); + assertSame('h265', $videoQuality->codec); + assertSame(4096, $videoQuality->fileSize); + } +} diff --git a/tests/Type/VideoTest.php b/tests/Type/VideoTest.php index 45eb27f6..b008c6dd 100644 --- a/tests/Type/VideoTest.php +++ b/tests/Type/VideoTest.php @@ -29,6 +29,7 @@ public function testBase(): void assertNull($video->fileSize); assertNull($video->cover); assertNull($video->startTimestamp); + assertNull($video->qualities); } public function testFromTelegramResult(): void @@ -60,6 +61,23 @@ public function testFromTelegramResult(): void ], ], 'start_timestamp' => 17, + 'qualities' => [ + [ + 'file_id' => 'fq1', + 'file_unique_id' => 'fuq1', + 'width' => 1920, + 'height' => 1080, + 'codec' => 'h264', + 'file_size' => 50000, + ], + [ + 'file_id' => 'fq2', + 'file_unique_id' => 'fuq2', + 'width' => 1280, + 'height' => 720, + 'codec' => 'h265', + ], + ], 'file_name' => 'face.png', 'mime_type' => 'image/png', 'file_size' => 123, @@ -78,5 +96,8 @@ public function testFromTelegramResult(): void assertSame('file_id-3', $video->cover[0]->fileId); assertSame('file_id-4', $video->cover[1]->fileId); assertSame(17, $video->startTimestamp); + assertCount(2, $video->qualities); + assertSame('fq1', $video->qualities[0]->fileId); + assertSame('fq2', $video->qualities[1]->fileId); } }