From 8d94c3c1252c1148f1129f81f89b0a11c48e532f Mon Sep 17 00:00:00 2001 From: OhYoung <212045739+ouyooung@users.noreply.github.com> Date: Thu, 12 Feb 2026 12:17:45 +0800 Subject: [PATCH 01/11] Added the field style to the classes KeyboardButton and InlineKeyboardButton, allowing bots to change the color of buttons. --- AUTHORS.rst | 1 + src/telegram/_inline/inlinekeyboardbutton.py | 50 +++++++++++++++++- src/telegram/_keyboardbutton.py | 54 ++++++++++++++++++-- src/telegram/constants.py | 47 +++++++++++++++++ 4 files changed, 148 insertions(+), 4 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 9ca986b53e5..ab4e7581466 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -104,6 +104,7 @@ The following wonderful people contributed directly or indirectly to this projec - `Oleg Shlyazhko `_ - `Oleg Sushchenko `_ - `Or Bin `_ +- `OuYoung `_ - `overquota `_ - `Pablo Martinez `_ - `Paradox `_ diff --git a/src/telegram/_inline/inlinekeyboardbutton.py b/src/telegram/_inline/inlinekeyboardbutton.py index 7114fac60e5..4970cb60b7b 100644 --- a/src/telegram/_inline/inlinekeyboardbutton.py +++ b/src/telegram/_inline/inlinekeyboardbutton.py @@ -40,7 +40,7 @@ class InlineKeyboardButton(TelegramObject): Objects of this class are comparable in terms of equality. Two objects of this class are considered equal, if their :attr:`text`, :attr:`url`, :attr:`login_url`, :attr:`callback_data`, :attr:`switch_inline_query`, :attr:`switch_inline_query_current_chat`, :attr:`callback_game`, - :attr:`web_app` and :attr:`pay` are equal. + :attr:`web_app`, :attr:`pay` and :attr:`style` are equal. Note: * Exactly one of the optional fields must be used to specify type of the button. @@ -77,6 +77,10 @@ class InlineKeyboardButton(TelegramObject): :attr:`web_app` is considered as well when comparing objects of this type in terms of equality. + .. versionchanged:: NEXT.VERSION + :attr:`style` is considered as well when comparing objects of this type in terms of + equality. + Args: text (:obj:`str`): Label text on the button. url (:obj:`str`, optional): HTTP or tg:// url to be opened when the button is pressed. @@ -141,6 +145,19 @@ class InlineKeyboardButton(TelegramObject): Note: This type of button **must** always be the first button in the first row and can only be used in invoice messages. + style (:obj:`str`, optional): Style of the button. Determines the visual appearance + of the button in supported Telegram clients. Possible values are + :tg-const:`telegram.KeyboardButtonStyle.PRIMARY`, + :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` and + :tg-const:`telegram.KeyboardButtonStyle.DANGER`. + Color aliases (BLUE, GREEN, RED) are also available. + + Note: + This feature requires Telegram client version 6.5.1 or later. Older clients + will display the button without styling. + + .. versionadded:: NEXT.VERSION + switch_inline_query_chosen_chat (:class:`telegram.SwitchInlineQueryChosenChat`, optional): If set, pressing the button will prompt the user to select one of their chats of the specified type, open that chat and insert the bot's username and the specified inline @@ -202,6 +219,18 @@ class InlineKeyboardButton(TelegramObject): copies the specified text to the clipboard. .. versionadded:: 21.7 + style (:obj:`str`, optional): Style of the button. Determines the visual appearance + of the button in supported Telegram clients. Possible values are + :tg-const:`telegram.KeyboardButtonStyle.PRIMARY`, + :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` and + :tg-const:`telegram.KeyboardButtonStyle.DANGER`. + Color aliases (BLUE, GREEN, RED) are also available. + + Note: + This feature requires Telegram client version 6.5.1 or later. Older clients + will display the button without styling. + + .. versionadded:: NEXT.VERSION callback_game (:class:`telegram.CallbackGame`): Optional. Description of the game that will be launched when the user presses the button. @@ -237,6 +266,7 @@ class InlineKeyboardButton(TelegramObject): "copy_text", "login_url", "pay", + "style", "switch_inline_query", "switch_inline_query_chosen_chat", "switch_inline_query_current_chat", @@ -258,6 +288,7 @@ def __init__( web_app: WebAppInfo | None = None, switch_inline_query_chosen_chat: SwitchInlineQueryChosenChat | None = None, copy_text: CopyTextButton | None = None, + style: str | None = None, *, api_kwargs: JSONDict | None = None, ): @@ -278,6 +309,7 @@ def __init__( switch_inline_query_chosen_chat ) self.copy_text: CopyTextButton | None = copy_text + self.style: str | None = style self._id_attrs = () self._set_id_attrs() @@ -294,6 +326,7 @@ def _set_id_attrs(self) -> None: self.switch_inline_query_current_chat, self.callback_game, self.pay, + self.style, ) @classmethod @@ -335,3 +368,18 @@ def update_callback_data(self, callback_data: str | object) -> None: .. versionadded:: 20.0 """ + PRIMARY: Final[str] = constants.KeyboardButtonStyle.PRIMARY + """:const:`telegram.constants.KeyboardButtonStyle.PRIMARY` + + .. versionadded:: NEXT.VERSION + """ + SUCCESS: Final[str] = constants.KeyboardButtonStyle.SUCCESS + """:const:`telegram.constants.KeyboardButtonStyle.SUCCESS` + + .. versionadded:: NEXT.VERSION + """ + DANGER: Final[str] = constants.KeyboardButtonStyle.DANGER + """:const:`telegram.constants.KeyboardButtonStyle.DANGER` + + .. versionadded:: NEXT.VERSION + """ diff --git a/src/telegram/_keyboardbutton.py b/src/telegram/_keyboardbutton.py index a08e966c35e..e5d5d80b9d5 100644 --- a/src/telegram/_keyboardbutton.py +++ b/src/telegram/_keyboardbutton.py @@ -18,8 +18,9 @@ # along with this program. If not, see [http://www.gnu.org/licenses/]. """This module contains an object that represents a Telegram KeyboardButton.""" -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Final +from telegram import constants from telegram._keyboardbuttonpolltype import KeyboardButtonPollType from telegram._keyboardbuttonrequest import KeyboardButtonRequestChat, KeyboardButtonRequestUsers from telegram._telegramobject import TelegramObject @@ -39,8 +40,8 @@ class KeyboardButton(TelegramObject): Objects of this class are comparable in terms of equality. Two objects of this class are considered equal, if their :attr:`text`, :attr:`request_contact`, :attr:`request_location`, - :attr:`request_poll`, :attr:`web_app`, :attr:`request_users` and :attr:`request_chat` are - equal. + :attr:`request_poll`, :attr:`web_app`, :attr:`request_users`, :attr:`request_chat` and + :attr:`style` are equal. Note: * Optional fields are mutually exclusive. @@ -53,6 +54,8 @@ class KeyboardButton(TelegramObject): * :attr:`request_users` and :attr:`request_chat` options will only work in Telegram versions released after 3 February, 2023. Older clients will display unsupported message. + * :attr:`style` option will only work in Telegram versions released after [DATE]. + Older clients will display buttons without styling. .. versionchanged:: 21.0 Removed deprecated argument and attribute ``request_user``. @@ -63,6 +66,10 @@ class KeyboardButton(TelegramObject): :attr:`request_users` and :attr:`request_chat` are considered as well when comparing objects of this type in terms of equality. + .. versionchanged:: NEXT.VERSION + :attr:`style` is considered as well when comparing objects of this type in terms of + equality. + Args: text (:obj:`str`): Text of the button. If none of the optional fields are used, it will be sent to the bot as a message when the button is pressed. @@ -92,6 +99,19 @@ class KeyboardButton(TelegramObject): Available in private chats only. .. versionadded:: 20.1 + style (:obj:`str`, optional): Style of the button. Determines the visual appearance + of the button in supported Telegram clients. Possible values are + :tg-const:`telegram.KeyboardButtonStyle.PRIMARY`, + :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` and + :tg-const:`telegram.KeyboardButtonStyle.DANGER`. + Color aliases (BLUE, GREEN, RED) are also available. + + Note: + This feature requires Telegram client version 6.5.1 or later. Older clients + will display the button without styling. + + .. versionadded:: NEXT.VERSION + Attributes: text (:obj:`str`): Text of the button. If none of the optional fields are used, it will be sent to the bot as a message when the button is pressed. @@ -120,6 +140,14 @@ class KeyboardButton(TelegramObject): Available in private chats only. .. versionadded:: 20.1 + style (:obj:`str`): Optional. Style of the button. Determines the visual appearance + of the button in supported Telegram clients. + :tg-const:`telegram.KeyboardButtonStyle.PRIMARY`, + :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` and + :tg-const:`telegram.KeyboardButtonStyle.DANGER`. + Color aliases (BLUE, GREEN, RED) are also available. + + .. versionadded:: NEXT.VERSION """ __slots__ = ( @@ -128,6 +156,7 @@ class KeyboardButton(TelegramObject): "request_location", "request_poll", "request_users", + "style", "text", "web_app", ) @@ -141,6 +170,7 @@ def __init__( web_app: WebAppInfo | None = None, request_chat: KeyboardButtonRequestChat | None = None, request_users: KeyboardButtonRequestUsers | None = None, + style: str | None = None, *, api_kwargs: JSONDict | None = None, ): @@ -155,6 +185,7 @@ def __init__( self.web_app: WebAppInfo | None = web_app self.request_users: KeyboardButtonRequestUsers | None = request_users self.request_chat: KeyboardButtonRequestChat | None = request_chat + self.style: str | None = style self._id_attrs = ( self.text, @@ -164,6 +195,7 @@ def __init__( self.web_app, self.request_users, self.request_chat, + self.style, ) self._freeze() @@ -191,3 +223,19 @@ def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "KeyboardButton": api_kwargs = {"request_user": request_user} return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs) + + PRIMARY: Final[str] = constants.KeyboardButtonStyle.PRIMARY + """:const:`telegram.constants.KeyboardButtonStyle.PRIMARY` + + .. versionadded:: NEXT.VERSION + """ + SUCCESS: Final[str] = constants.KeyboardButtonStyle.SUCCESS + """:const:`telegram.constants.KeyboardButtonStyle.SUCCESS` + + .. versionadded:: NEXT.VERSION + """ + DANGER: Final[str] = constants.KeyboardButtonStyle.DANGER + """:const:`telegram.constants.KeyboardButtonStyle.DANGER` + + .. versionadded:: NEXT.VERSION + """ diff --git a/src/telegram/constants.py b/src/telegram/constants.py index 82854ef597d..07ce9dc6f79 100644 --- a/src/telegram/constants.py +++ b/src/telegram/constants.py @@ -1402,6 +1402,53 @@ class InlineKeyboardButtonLimit(IntEnum): """ +class KeyboardButtonStyle(StringEnum): + """This enum contains the available button styles for + :class:`telegram.InlineKeyboardButton` and :class:`telegram.KeyboardButton`. + The enum members of this enumeration are instances of :class:`str` and can be treated as such. + + .. versionadded:: NEXT.VERSION + """ + + __slots__ = () + + PRIMARY = "primary" + """:obj:`str`: Primary button style (usually blue) for the + :paramref:`~telegram.InlineKeyboardButton.style` and + :paramref:`~telegram.KeyboardButton.style` parameters. + """ + + SUCCESS = "success" + """:obj:`str`: Success button style (usually green) for the + :paramref:`~telegram.InlineKeyboardButton.style` and + :paramref:`~telegram.KeyboardButton.style` parameters. + """ + + DANGER = "danger" + """:obj:`str`: Danger/destructive button style (usually red) for the + :paramref:`~telegram.InlineKeyboardButton.style` and + :paramref:`~telegram.KeyboardButton.style` parameters. + """ + + BLUE = "primary" + """:obj:`str`: Alias for :attr:`PRIMARY`. Blue button style for the + :paramref:`~telegram.InlineKeyboardButton.style` and + :paramref:`~telegram.KeyboardButton.style` parameters. + """ + + GREEN = "success" + """:obj:`str`: Alias for :attr:`SUCCESS`. Green button style for the + :paramref:`~telegram.InlineKeyboardButton.style` and + :paramref:`~telegram.KeyboardButton.style` parameters. + """ + + RED = "danger" + """:obj:`str`: Alias for :attr:`DANGER`. Red button style for the + :paramref:`~telegram.InlineKeyboardButton.style` and + :paramref:`~telegram.KeyboardButton.style` parameters. + """ + + class InlineKeyboardMarkupLimit(IntEnum): """This enum contains limitations for :class:`telegram.InlineKeyboardMarkup`/ :meth:`telegram.Bot.send_message` & friends. The enum From 0c8f261adf103247ad5b6bc71ff457226c4a8ee0 Mon Sep 17 00:00:00 2001 From: OhYoung <212045739+ouyooung@users.noreply.github.com> Date: Thu, 12 Feb 2026 19:01:51 +0800 Subject: [PATCH 02/11] Updates to the `icon_custom_emoji_id` and `style` fields --- src/telegram/_inline/inlinekeyboardbutton.py | 50 +++++++++++++----- src/telegram/_keyboardbutton.py | 54 ++++++++++++++------ src/telegram/constants.py | 1 + tests/_inline/test_inlinekeyboardbutton.py | 39 ++++++++++++++ tests/test_constants.py | 8 +++ tests/test_keyboardbutton.py | 36 +++++++++++++ 6 files changed, 159 insertions(+), 29 deletions(-) diff --git a/src/telegram/_inline/inlinekeyboardbutton.py b/src/telegram/_inline/inlinekeyboardbutton.py index 4970cb60b7b..9c2313551a3 100644 --- a/src/telegram/_inline/inlinekeyboardbutton.py +++ b/src/telegram/_inline/inlinekeyboardbutton.py @@ -40,7 +40,7 @@ class InlineKeyboardButton(TelegramObject): Objects of this class are comparable in terms of equality. Two objects of this class are considered equal, if their :attr:`text`, :attr:`url`, :attr:`login_url`, :attr:`callback_data`, :attr:`switch_inline_query`, :attr:`switch_inline_query_current_chat`, :attr:`callback_game`, - :attr:`web_app`, :attr:`pay` and :attr:`style` are equal. + :attr:`web_app`, :attr:`pay`, :attr:`style` and :attr:`icon_custom_emoji_id` are equal. Note: * Exactly one of the optional fields must be used to specify type of the button. @@ -58,6 +58,9 @@ class InlineKeyboardButton(TelegramObject): This will only work in Telegram versions released after December 7, 2021. Older clients will display *unsupported message*. + * :attr:`style` option will only work in Telegram versions released after 6.5.1. + Older clients will display buttons without styling. + Warning: * If your bot allows your arbitrary callback data, buttons whose callback data is a non-hashable object will become unhashable. Trying to evaluate ``hash(button)`` will @@ -145,19 +148,27 @@ class InlineKeyboardButton(TelegramObject): Note: This type of button **must** always be the first button in the first row and can only be used in invoice messages. - style (:obj:`str`, optional): Style of the button. Determines the visual appearance - of the button in supported Telegram clients. Possible values are - :tg-const:`telegram.KeyboardButtonStyle.PRIMARY`, - :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` and - :tg-const:`telegram.KeyboardButtonStyle.DANGER`. - Color aliases (BLUE, GREEN, RED) are also available. + style (:obj:`str`): Optional. Style of the button. Determines the visual appearance + of the button in supported Telegram clients. Only three values are supported: + :tg-const:`telegram.KeyboardButtonStyle.PRIMARY` (blue), + :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` (green), and + :tg-const:`telegram.KeyboardButtonStyle.DANGER` (red). + Color name aliases :tg-const:`telegram.KeyboardButtonStyle.BLUE`, + :tg-const:`telegram.KeyboardButtonStyle.GREEN`, and + :tg-const:`telegram.KeyboardButtonStyle.RED` are also available. Note: This feature requires Telegram client version 6.5.1 or later. Older clients will display the button without styling. .. versionadded:: NEXT.VERSION + icon_custom_emoji_id (:obj:`str`): Optional. Unique identifier of the + custom emoji shown before the text of the button. Can only be used by bots that + purchased additional usernames on Fragment or in the messages directly sent by the + bot to private, group and supergroup chats if the owner of the bot has a Telegram + Premium subscription. + .. versionadded:: NEXT.VERSION switch_inline_query_chosen_chat (:class:`telegram.SwitchInlineQueryChosenChat`, optional): If set, pressing the button will prompt the user to select one of their chats of the specified type, open that chat and insert the bot's username and the specified inline @@ -219,17 +230,26 @@ class InlineKeyboardButton(TelegramObject): copies the specified text to the clipboard. .. versionadded:: 21.7 - style (:obj:`str`, optional): Style of the button. Determines the visual appearance - of the button in supported Telegram clients. Possible values are - :tg-const:`telegram.KeyboardButtonStyle.PRIMARY`, - :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` and - :tg-const:`telegram.KeyboardButtonStyle.DANGER`. - Color aliases (BLUE, GREEN, RED) are also available. + style (:obj:`str`): Optional. Style of the button. Determines the visual appearance + of the button in supported Telegram clients. Only three values are supported: + :tg-const:`telegram.KeyboardButtonStyle.PRIMARY` (blue), + :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` (green), and + :tg-const:`telegram.KeyboardButtonStyle.DANGER` (red). + Color name aliases :tg-const:`telegram.KeyboardButtonStyle.BLUE`, + :tg-const:`telegram.KeyboardButtonStyle.GREEN`, and + :tg-const:`telegram.KeyboardButtonStyle.RED` are also available. Note: This feature requires Telegram client version 6.5.1 or later. Older clients will display the button without styling. + .. versionadded:: NEXT.VERSION + icon_custom_emoji_id (:obj:`str`): Optional. Unique identifier of the + custom emoji shown before the text of the button. Can only be used by bots that + purchased additional usernames on Fragment or in the messages directly sent by the + bot to private, group and supergroup chats if the owner of the bot has a Telegram + Premium subscription. + .. versionadded:: NEXT.VERSION callback_game (:class:`telegram.CallbackGame`): Optional. Description of the game that will be launched when the user presses the button. @@ -264,6 +284,7 @@ class InlineKeyboardButton(TelegramObject): "callback_data", "callback_game", "copy_text", + "icon_custom_emoji_id", "login_url", "pay", "style", @@ -289,6 +310,7 @@ def __init__( switch_inline_query_chosen_chat: SwitchInlineQueryChosenChat | None = None, copy_text: CopyTextButton | None = None, style: str | None = None, + icon_custom_emoji_id: str | None = None, *, api_kwargs: JSONDict | None = None, ): @@ -310,6 +332,7 @@ def __init__( ) self.copy_text: CopyTextButton | None = copy_text self.style: str | None = style + self.icon_custom_emoji_id: str | None = icon_custom_emoji_id self._id_attrs = () self._set_id_attrs() @@ -327,6 +350,7 @@ def _set_id_attrs(self) -> None: self.callback_game, self.pay, self.style, + self.icon_custom_emoji_id, ) @classmethod diff --git a/src/telegram/_keyboardbutton.py b/src/telegram/_keyboardbutton.py index e5d5d80b9d5..ac3144ba39d 100644 --- a/src/telegram/_keyboardbutton.py +++ b/src/telegram/_keyboardbutton.py @@ -40,8 +40,8 @@ class KeyboardButton(TelegramObject): Objects of this class are comparable in terms of equality. Two objects of this class are considered equal, if their :attr:`text`, :attr:`request_contact`, :attr:`request_location`, - :attr:`request_poll`, :attr:`web_app`, :attr:`request_users`, :attr:`request_chat` and - :attr:`style` are equal. + :attr:`request_poll`, :attr:`web_app`, :attr:`request_users`, :attr:`request_chat`, + :attr:`style` and :attr:`icon_custom_emoji_id` are equal. Note: * Optional fields are mutually exclusive. @@ -54,7 +54,7 @@ class KeyboardButton(TelegramObject): * :attr:`request_users` and :attr:`request_chat` options will only work in Telegram versions released after 3 February, 2023. Older clients will display unsupported message. - * :attr:`style` option will only work in Telegram versions released after [DATE]. + * :attr:`style` option will only work in Telegram versions released after 6.5.1. Older clients will display buttons without styling. .. versionchanged:: 21.0 @@ -67,8 +67,8 @@ class KeyboardButton(TelegramObject): comparing objects of this type in terms of equality. .. versionchanged:: NEXT.VERSION - :attr:`style` is considered as well when comparing objects of this type in terms of - equality. + :attr:`style` and :attr:`icon_custom_emoji_id` are considered as well when + comparing objects of this type in terms of equality. Args: text (:obj:`str`): Text of the button. If none of the optional fields are used, it will be @@ -99,18 +99,27 @@ class KeyboardButton(TelegramObject): Available in private chats only. .. versionadded:: 20.1 - style (:obj:`str`, optional): Style of the button. Determines the visual appearance - of the button in supported Telegram clients. Possible values are - :tg-const:`telegram.KeyboardButtonStyle.PRIMARY`, - :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` and - :tg-const:`telegram.KeyboardButtonStyle.DANGER`. - Color aliases (BLUE, GREEN, RED) are also available. + style (:obj:`str`): Optional. Style of the button. Determines the visual appearance + of the button in supported Telegram clients. Only three values are supported: + :tg-const:`telegram.KeyboardButtonStyle.PRIMARY` (blue), + :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` (green), and + :tg-const:`telegram.KeyboardButtonStyle.DANGER` (red). + Color name aliases :tg-const:`telegram.KeyboardButtonStyle.BLUE`, + :tg-const:`telegram.KeyboardButtonStyle.GREEN`, and + :tg-const:`telegram.KeyboardButtonStyle.RED` are also available. Note: This feature requires Telegram client version 6.5.1 or later. Older clients will display the button without styling. .. versionadded:: NEXT.VERSION + icon_custom_emoji_id (:obj:`str`): Optional. Unique identifier of the + custom emoji shown before the text of the button. Can only be used by bots that + purchased additional usernames on Fragment or in the messages directly sent by the + bot to private, group and supergroup chats if the owner of the bot has a Telegram + Premium subscription. + + .. versionadded:: NEXT.VERSION Attributes: text (:obj:`str`): Text of the button. If none of the optional fields are used, it will be @@ -141,16 +150,26 @@ class KeyboardButton(TelegramObject): .. versionadded:: 20.1 style (:obj:`str`): Optional. Style of the button. Determines the visual appearance - of the button in supported Telegram clients. - :tg-const:`telegram.KeyboardButtonStyle.PRIMARY`, - :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` and - :tg-const:`telegram.KeyboardButtonStyle.DANGER`. - Color aliases (BLUE, GREEN, RED) are also available. + of the button in supported Telegram clients. Only three values are supported: + :tg-const:`telegram.KeyboardButtonStyle.PRIMARY` (blue), + :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` (green), and + :tg-const:`telegram.KeyboardButtonStyle.DANGER` (red). + Color name aliases :tg-const:`telegram.KeyboardButtonStyle.BLUE`, + :tg-const:`telegram.KeyboardButtonStyle.GREEN`, and + :tg-const:`telegram.KeyboardButtonStyle.RED` are also available. + + .. versionadded:: NEXT.VERSION + icon_custom_emoji_id (:obj:`str`): Optional. Unique identifier of the + custom emoji shown before the text of the button. Can only be used by bots that + purchased additional usernames on Fragment or in the messages directly sent by the + bot to private, group and supergroup chats if the owner of the bot has a Telegram + Premium subscription. .. versionadded:: NEXT.VERSION """ __slots__ = ( + "icon_custom_emoji_id", "request_chat", "request_contact", "request_location", @@ -171,6 +190,7 @@ def __init__( request_chat: KeyboardButtonRequestChat | None = None, request_users: KeyboardButtonRequestUsers | None = None, style: str | None = None, + icon_custom_emoji_id: str | None = None, *, api_kwargs: JSONDict | None = None, ): @@ -186,6 +206,7 @@ def __init__( self.request_users: KeyboardButtonRequestUsers | None = request_users self.request_chat: KeyboardButtonRequestChat | None = request_chat self.style: str | None = style + self.icon_custom_emoji_id: str | None = icon_custom_emoji_id self._id_attrs = ( self.text, @@ -196,6 +217,7 @@ def __init__( self.request_users, self.request_chat, self.style, + self.icon_custom_emoji_id, ) self._freeze() diff --git a/src/telegram/constants.py b/src/telegram/constants.py index 07ce9dc6f79..972943c8c50 100644 --- a/src/telegram/constants.py +++ b/src/telegram/constants.py @@ -85,6 +85,7 @@ "InputStoryContentType", "InvoiceLimit", "KeyboardButtonRequestUsersLimit", + "KeyboardButtonStyle", "LocationLimit", "MaskPosition", "MediaGroupLimit", diff --git a/tests/_inline/test_inlinekeyboardbutton.py b/tests/_inline/test_inlinekeyboardbutton.py index f1f0f798931..152e6b43f8e 100644 --- a/tests/_inline/test_inlinekeyboardbutton.py +++ b/tests/_inline/test_inlinekeyboardbutton.py @@ -48,6 +48,8 @@ def inline_keyboard_button(): InlineKeyboardButtonTestBase.switch_inline_query_chosen_chat ), copy_text=InlineKeyboardButtonTestBase.copy_text, + style=InlineKeyboardButtonTestBase.style, + icon_custom_emoji_id=InlineKeyboardButtonTestBase.icon_custom_emoji_id, ) @@ -63,6 +65,8 @@ class InlineKeyboardButtonTestBase: web_app = WebAppInfo(url="https://example.com") switch_inline_query_chosen_chat = SwitchInlineQueryChosenChat("a_bot", True, False, True, True) copy_text = CopyTextButton("python-telegram-bot") + style = "danger" + icon_custom_emoji_id = "5237829955978547322" class TestInlineKeyboardButtonWithoutRequest(InlineKeyboardButtonTestBase): @@ -90,6 +94,8 @@ def test_expected_values(self, inline_keyboard_button): == self.switch_inline_query_chosen_chat ) assert inline_keyboard_button.copy_text == self.copy_text + assert inline_keyboard_button.style == self.style + assert inline_keyboard_button.icon_custom_emoji_id == self.icon_custom_emoji_id def test_to_dict(self, inline_keyboard_button): inline_keyboard_button_dict = inline_keyboard_button.to_dict() @@ -122,6 +128,11 @@ def test_to_dict(self, inline_keyboard_button): assert ( inline_keyboard_button_dict["copy_text"] == inline_keyboard_button.copy_text.to_dict() ) + assert inline_keyboard_button_dict["style"] == inline_keyboard_button.style + assert ( + inline_keyboard_button_dict["icon_custom_emoji_id"] + == inline_keyboard_button.icon_custom_emoji_id + ) def test_de_json(self, offline_bot): json_dict = { @@ -136,6 +147,8 @@ def test_de_json(self, offline_bot): "pay": self.pay, "switch_inline_query_chosen_chat": self.switch_inline_query_chosen_chat.to_dict(), "copy_text": self.copy_text.to_dict(), + "style": self.style, + "icon_custom_emoji_id": self.icon_custom_emoji_id, } inline_keyboard_button = InlineKeyboardButton.de_json(json_dict, None) @@ -158,6 +171,8 @@ def test_de_json(self, offline_bot): == self.switch_inline_query_chosen_chat ) assert inline_keyboard_button.copy_text == self.copy_text + assert inline_keyboard_button.style == self.style + assert inline_keyboard_button.icon_custom_emoji_id == self.icon_custom_emoji_id def test_equality(self): a = InlineKeyboardButton("text", callback_data="data") @@ -167,6 +182,12 @@ def test_equality(self): e = InlineKeyboardButton("text", url="http://google.com") f = InlineKeyboardButton("text", web_app=WebAppInfo(url="https://ptb.org")) g = LoginUrl("http://google.com") + h = InlineKeyboardButton("test", style="primary") + i = InlineKeyboardButton("test", style="success") + j = InlineKeyboardButton("test", style="primary") + k = InlineKeyboardButton("test", icon_custom_emoji_id="123") + m = InlineKeyboardButton("test", icon_custom_emoji_id="456") + n = InlineKeyboardButton("test", icon_custom_emoji_id="123") assert a == b assert hash(a) == hash(b) @@ -186,6 +207,24 @@ def test_equality(self): assert a != g assert hash(a) != hash(g) + assert a != h + assert hash(a) != hash(h) + + assert h != i + assert hash(h) != hash(i) + + assert h == j + assert hash(h) == hash(j) + + assert a != k + assert hash(a) != hash(k) + + assert k != m + assert hash(k) != hash(m) + + assert k == n + assert hash(k) == hash(n) + @pytest.mark.parametrize("callback_data", ["foo", 1, ("da", "ta"), object()]) def test_update_callback_data(self, callback_data): button = InlineKeyboardButton(text="test", callback_data="data") diff --git a/tests/test_constants.py b/tests/test_constants.py index 5611b5f80c7..05268033503 100644 --- a/tests/test_constants.py +++ b/tests/test_constants.py @@ -254,6 +254,14 @@ def test_message_attachment_type_completeness_reverse(self): except ValueError: pytest.fail(f"Missing MessageAttachmentType for {match.group(1)}") + def test_keyboard_button_style(self): + assert constants.KeyboardButtonStyle.PRIMARY == "primary" + assert constants.KeyboardButtonStyle.SUCCESS == "success" + assert constants.KeyboardButtonStyle.DANGER == "danger" + assert constants.KeyboardButtonStyle.BLUE == "primary" + assert constants.KeyboardButtonStyle.GREEN == "success" + assert constants.KeyboardButtonStyle.RED == "danger" + class TestConstantsWithRequest: async def test_max_message_length(self, bot, chat_id): diff --git a/tests/test_keyboardbutton.py b/tests/test_keyboardbutton.py index f7d14902784..cd68e68b39e 100644 --- a/tests/test_keyboardbutton.py +++ b/tests/test_keyboardbutton.py @@ -39,6 +39,8 @@ def keyboard_button(): web_app=KeyboardButtonTestBase.web_app, request_chat=KeyboardButtonTestBase.request_chat, request_users=KeyboardButtonTestBase.request_users, + style=KeyboardButtonTestBase.style, + icon_custom_emoji_id=KeyboardButtonTestBase.icon_custom_emoji_id, ) @@ -50,6 +52,8 @@ class KeyboardButtonTestBase: web_app = WebAppInfo(url="https://example.com") request_chat = KeyboardButtonRequestChat(1, True) request_users = KeyboardButtonRequestUsers(2) + style = "primary" + icon_custom_emoji_id = "5237829955978547322" class TestKeyboardButtonWithoutRequest(KeyboardButtonTestBase): @@ -67,6 +71,8 @@ def test_expected_values(self, keyboard_button): assert keyboard_button.web_app == self.web_app assert keyboard_button.request_chat == self.request_chat assert keyboard_button.request_users == self.request_users + assert keyboard_button.style == self.style + assert keyboard_button.icon_custom_emoji_id == self.icon_custom_emoji_id def test_to_dict(self, keyboard_button): keyboard_button_dict = keyboard_button.to_dict() @@ -79,6 +85,8 @@ def test_to_dict(self, keyboard_button): assert keyboard_button_dict["web_app"] == keyboard_button.web_app.to_dict() assert keyboard_button_dict["request_chat"] == keyboard_button.request_chat.to_dict() assert keyboard_button_dict["request_users"] == keyboard_button.request_users.to_dict() + assert keyboard_button_dict["style"] == keyboard_button.style + assert keyboard_button_dict["icon_custom_emoji_id"] == keyboard_button.icon_custom_emoji_id @pytest.mark.parametrize("request_user", [True, False]) def test_de_json(self, request_user): @@ -90,6 +98,8 @@ def test_de_json(self, request_user): "web_app": self.web_app.to_dict(), "request_chat": self.request_chat.to_dict(), "request_users": self.request_users.to_dict(), + "style": self.style, + "icon_custom_emoji_id": self.icon_custom_emoji_id, } if request_user: json_dict["request_user"] = {"request_id": 2} @@ -107,6 +117,8 @@ def test_de_json(self, request_user): assert keyboard_button.web_app == self.web_app assert keyboard_button.request_chat == self.request_chat assert keyboard_button.request_users == self.request_users + assert keyboard_button.style == self.style + assert keyboard_button.icon_custom_emoji_id == self.icon_custom_emoji_id def test_equality(self): a = KeyboardButton("test", request_contact=True) @@ -126,6 +138,12 @@ def test_equality(self): request_chat=KeyboardButtonRequestChat(1, False), request_users=KeyboardButtonRequestUsers(2), ) + h = KeyboardButton("test", request_contact=True, style="primary") + i = KeyboardButton("test", request_contact=True, style="success") + j = KeyboardButton("test", request_contact=True, style="primary") + k = KeyboardButton("test", request_contact=True, icon_custom_emoji_id="123") + m = KeyboardButton("test", request_contact=True, icon_custom_emoji_id="456") + n = KeyboardButton("test", request_contact=True, icon_custom_emoji_id="123") assert a == b assert hash(a) == hash(b) @@ -144,3 +162,21 @@ def test_equality(self): assert f == g assert hash(f) == hash(g) + + assert a != h + assert hash(a) != hash(h) + + assert h != i + assert hash(h) != hash(i) + + assert h == j + assert hash(h) == hash(j) + + assert a != k + assert hash(a) != hash(k) + + assert k != m + assert hash(k) != hash(m) + + assert k == n + assert hash(k) == hash(n) From d2b14c40e3f3b3385e3c1569a3b8586cf97cb876 Mon Sep 17 00:00:00 2001 From: OhYoung <212045739+ouyooung@users.noreply.github.com> Date: Thu, 12 Feb 2026 19:52:44 +0800 Subject: [PATCH 03/11] Update _keyboardbutton.py --- src/telegram/_keyboardbutton.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/telegram/_keyboardbutton.py b/src/telegram/_keyboardbutton.py index ac3144ba39d..9e19fe3a8de 100644 --- a/src/telegram/_keyboardbutton.py +++ b/src/telegram/_keyboardbutton.py @@ -108,10 +108,6 @@ class KeyboardButton(TelegramObject): :tg-const:`telegram.KeyboardButtonStyle.GREEN`, and :tg-const:`telegram.KeyboardButtonStyle.RED` are also available. - Note: - This feature requires Telegram client version 6.5.1 or later. Older clients - will display the button without styling. - .. versionadded:: NEXT.VERSION icon_custom_emoji_id (:obj:`str`): Optional. Unique identifier of the custom emoji shown before the text of the button. Can only be used by bots that @@ -158,6 +154,10 @@ class KeyboardButton(TelegramObject): :tg-const:`telegram.KeyboardButtonStyle.GREEN`, and :tg-const:`telegram.KeyboardButtonStyle.RED` are also available. + Note: + This feature requires Telegram client version 6.5.1 or later. Older clients + will display the button without styling. + .. versionadded:: NEXT.VERSION icon_custom_emoji_id (:obj:`str`): Optional. Unique identifier of the custom emoji shown before the text of the button. Can only be used by bots that From 9209963577ebed609bb66c92c6e64d194bdebf66 Mon Sep 17 00:00:00 2001 From: OhYoung <212045739+ouyooung@users.noreply.github.com> Date: Fri, 13 Feb 2026 05:50:33 +0800 Subject: [PATCH 04/11] Create chango --- changes/unreleased/5126.4HWsCMNxMeNeMnEkJMzKRi.toml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changes/unreleased/5126.4HWsCMNxMeNeMnEkJMzKRi.toml diff --git a/changes/unreleased/5126.4HWsCMNxMeNeMnEkJMzKRi.toml b/changes/unreleased/5126.4HWsCMNxMeNeMnEkJMzKRi.toml new file mode 100644 index 00000000000..a6c105c895f --- /dev/null +++ b/changes/unreleased/5126.4HWsCMNxMeNeMnEkJMzKRi.toml @@ -0,0 +1,5 @@ +other = "Updates to the icon_custom_emoji_id and style fields" +[[pull_requests]] +uid = "5126" +author_uids = ["ouyooung"] +closes_threads = [] From 116ac0281ea01ef6a2d91c8ebc3d6c3503e70b8c Mon Sep 17 00:00:00 2001 From: OhYoung <212045739+ouyooung@users.noreply.github.com> Date: Fri, 13 Feb 2026 05:53:17 +0800 Subject: [PATCH 05/11] Update chango --- ...CMNxMeNeMnEkJMzKRi.toml => 5133.4HWsCMNxMeNeMnEkJMzKRi.toml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename changes/unreleased/{5126.4HWsCMNxMeNeMnEkJMzKRi.toml => 5133.4HWsCMNxMeNeMnEkJMzKRi.toml} (90%) diff --git a/changes/unreleased/5126.4HWsCMNxMeNeMnEkJMzKRi.toml b/changes/unreleased/5133.4HWsCMNxMeNeMnEkJMzKRi.toml similarity index 90% rename from changes/unreleased/5126.4HWsCMNxMeNeMnEkJMzKRi.toml rename to changes/unreleased/5133.4HWsCMNxMeNeMnEkJMzKRi.toml index a6c105c895f..b8236bd128b 100644 --- a/changes/unreleased/5126.4HWsCMNxMeNeMnEkJMzKRi.toml +++ b/changes/unreleased/5133.4HWsCMNxMeNeMnEkJMzKRi.toml @@ -1,5 +1,5 @@ other = "Updates to the icon_custom_emoji_id and style fields" [[pull_requests]] -uid = "5126" +uid = "5133" author_uids = ["ouyooung"] closes_threads = [] From 9d39ee8a83a1af7ca03ba6cdee8d4a9df28a5082 Mon Sep 17 00:00:00 2001 From: OhYoung <212045739+ouyooung@users.noreply.github.com> Date: Fri, 13 Feb 2026 06:30:18 +0800 Subject: [PATCH 06/11] update tests --- tests/_inline/test_inlinekeyboardbutton.py | 18 +----------------- tests/test_constants.py | 3 --- tests/test_keyboardbutton.py | 18 +----------------- 3 files changed, 2 insertions(+), 37 deletions(-) diff --git a/tests/_inline/test_inlinekeyboardbutton.py b/tests/_inline/test_inlinekeyboardbutton.py index 152e6b43f8e..1651d73582a 100644 --- a/tests/_inline/test_inlinekeyboardbutton.py +++ b/tests/_inline/test_inlinekeyboardbutton.py @@ -183,11 +183,7 @@ def test_equality(self): f = InlineKeyboardButton("text", web_app=WebAppInfo(url="https://ptb.org")) g = LoginUrl("http://google.com") h = InlineKeyboardButton("test", style="primary") - i = InlineKeyboardButton("test", style="success") - j = InlineKeyboardButton("test", style="primary") - k = InlineKeyboardButton("test", icon_custom_emoji_id="123") - m = InlineKeyboardButton("test", icon_custom_emoji_id="456") - n = InlineKeyboardButton("test", icon_custom_emoji_id="123") + i = InlineKeyboardButton("test", icon_custom_emoji_id="123") assert a == b assert hash(a) == hash(b) @@ -213,18 +209,6 @@ def test_equality(self): assert h != i assert hash(h) != hash(i) - assert h == j - assert hash(h) == hash(j) - - assert a != k - assert hash(a) != hash(k) - - assert k != m - assert hash(k) != hash(m) - - assert k == n - assert hash(k) == hash(n) - @pytest.mark.parametrize("callback_data", ["foo", 1, ("da", "ta"), object()]) def test_update_callback_data(self, callback_data): button = InlineKeyboardButton(text="test", callback_data="data") diff --git a/tests/test_constants.py b/tests/test_constants.py index 05268033503..8c5c57f1e41 100644 --- a/tests/test_constants.py +++ b/tests/test_constants.py @@ -258,9 +258,6 @@ def test_keyboard_button_style(self): assert constants.KeyboardButtonStyle.PRIMARY == "primary" assert constants.KeyboardButtonStyle.SUCCESS == "success" assert constants.KeyboardButtonStyle.DANGER == "danger" - assert constants.KeyboardButtonStyle.BLUE == "primary" - assert constants.KeyboardButtonStyle.GREEN == "success" - assert constants.KeyboardButtonStyle.RED == "danger" class TestConstantsWithRequest: diff --git a/tests/test_keyboardbutton.py b/tests/test_keyboardbutton.py index cd68e68b39e..f2b5f6f1a8c 100644 --- a/tests/test_keyboardbutton.py +++ b/tests/test_keyboardbutton.py @@ -139,11 +139,7 @@ def test_equality(self): request_users=KeyboardButtonRequestUsers(2), ) h = KeyboardButton("test", request_contact=True, style="primary") - i = KeyboardButton("test", request_contact=True, style="success") - j = KeyboardButton("test", request_contact=True, style="primary") - k = KeyboardButton("test", request_contact=True, icon_custom_emoji_id="123") - m = KeyboardButton("test", request_contact=True, icon_custom_emoji_id="456") - n = KeyboardButton("test", request_contact=True, icon_custom_emoji_id="123") + i = KeyboardButton("test", request_contact=True, icon_custom_emoji_id="123") assert a == b assert hash(a) == hash(b) @@ -168,15 +164,3 @@ def test_equality(self): assert h != i assert hash(h) != hash(i) - - assert h == j - assert hash(h) == hash(j) - - assert a != k - assert hash(a) != hash(k) - - assert k != m - assert hash(k) != hash(m) - - assert k == n - assert hash(k) == hash(n) From 0d66c94c4597d864c0510c81127a674e8e617875 Mon Sep 17 00:00:00 2001 From: OuYoung <212045739+ouyooung@users.noreply.github.com> Date: Sat, 14 Feb 2026 19:20:31 +0800 Subject: [PATCH 07/11] Update src/telegram/_inline/inlinekeyboardbutton.py Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com> --- src/telegram/_inline/inlinekeyboardbutton.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/telegram/_inline/inlinekeyboardbutton.py b/src/telegram/_inline/inlinekeyboardbutton.py index 9c2313551a3..e59f49a9dfe 100644 --- a/src/telegram/_inline/inlinekeyboardbutton.py +++ b/src/telegram/_inline/inlinekeyboardbutton.py @@ -162,7 +162,7 @@ class InlineKeyboardButton(TelegramObject): will display the button without styling. .. versionadded:: NEXT.VERSION - icon_custom_emoji_id (:obj:`str`): Optional. Unique identifier of the + icon_custom_emoji_id (:obj:`str`, optional): Unique identifier of the custom emoji shown before the text of the button. Can only be used by bots that purchased additional usernames on Fragment or in the messages directly sent by the bot to private, group and supergroup chats if the owner of the bot has a Telegram From d40cda24039d719b3d2395ce0fb80cb54d5b612a Mon Sep 17 00:00:00 2001 From: OhYoung <212045739+ouyooung@users.noreply.github.com> Date: Sat, 14 Feb 2026 21:11:26 +0800 Subject: [PATCH 08/11] Update constants --- src/telegram/_inline/inlinekeyboardbutton.py | 19 ++----------------- src/telegram/_keyboardbutton.py | 16 ---------------- tests/test_constants.py | 3 +++ 3 files changed, 5 insertions(+), 33 deletions(-) diff --git a/src/telegram/_inline/inlinekeyboardbutton.py b/src/telegram/_inline/inlinekeyboardbutton.py index e59f49a9dfe..e734e59bf20 100644 --- a/src/telegram/_inline/inlinekeyboardbutton.py +++ b/src/telegram/_inline/inlinekeyboardbutton.py @@ -81,8 +81,8 @@ class InlineKeyboardButton(TelegramObject): equality. .. versionchanged:: NEXT.VERSION - :attr:`style` is considered as well when comparing objects of this type in terms of - equality. + :attr:`style` and :attr:`icon_custom_emoji_id` are considered as well when + comparing objects of this type in terms of equality. Args: text (:obj:`str`): Label text on the button. @@ -392,18 +392,3 @@ def update_callback_data(self, callback_data: str | object) -> None: .. versionadded:: 20.0 """ - PRIMARY: Final[str] = constants.KeyboardButtonStyle.PRIMARY - """:const:`telegram.constants.KeyboardButtonStyle.PRIMARY` - - .. versionadded:: NEXT.VERSION - """ - SUCCESS: Final[str] = constants.KeyboardButtonStyle.SUCCESS - """:const:`telegram.constants.KeyboardButtonStyle.SUCCESS` - - .. versionadded:: NEXT.VERSION - """ - DANGER: Final[str] = constants.KeyboardButtonStyle.DANGER - """:const:`telegram.constants.KeyboardButtonStyle.DANGER` - - .. versionadded:: NEXT.VERSION - """ diff --git a/src/telegram/_keyboardbutton.py b/src/telegram/_keyboardbutton.py index 9e19fe3a8de..934137b8773 100644 --- a/src/telegram/_keyboardbutton.py +++ b/src/telegram/_keyboardbutton.py @@ -245,19 +245,3 @@ def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "KeyboardButton": api_kwargs = {"request_user": request_user} return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs) - - PRIMARY: Final[str] = constants.KeyboardButtonStyle.PRIMARY - """:const:`telegram.constants.KeyboardButtonStyle.PRIMARY` - - .. versionadded:: NEXT.VERSION - """ - SUCCESS: Final[str] = constants.KeyboardButtonStyle.SUCCESS - """:const:`telegram.constants.KeyboardButtonStyle.SUCCESS` - - .. versionadded:: NEXT.VERSION - """ - DANGER: Final[str] = constants.KeyboardButtonStyle.DANGER - """:const:`telegram.constants.KeyboardButtonStyle.DANGER` - - .. versionadded:: NEXT.VERSION - """ diff --git a/tests/test_constants.py b/tests/test_constants.py index 8c5c57f1e41..05268033503 100644 --- a/tests/test_constants.py +++ b/tests/test_constants.py @@ -258,6 +258,9 @@ def test_keyboard_button_style(self): assert constants.KeyboardButtonStyle.PRIMARY == "primary" assert constants.KeyboardButtonStyle.SUCCESS == "success" assert constants.KeyboardButtonStyle.DANGER == "danger" + assert constants.KeyboardButtonStyle.BLUE == "primary" + assert constants.KeyboardButtonStyle.GREEN == "success" + assert constants.KeyboardButtonStyle.RED == "danger" class TestConstantsWithRequest: From 0036cc4bca8c1abe8ada13c6644f2d03f0044540 Mon Sep 17 00:00:00 2001 From: OhYoung <212045739+ouyooung@users.noreply.github.com> Date: Sat, 14 Feb 2026 21:16:37 +0800 Subject: [PATCH 09/11] Update _keyboardbutton.py --- src/telegram/_keyboardbutton.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/telegram/_keyboardbutton.py b/src/telegram/_keyboardbutton.py index 934137b8773..1b757e5dc3a 100644 --- a/src/telegram/_keyboardbutton.py +++ b/src/telegram/_keyboardbutton.py @@ -18,9 +18,8 @@ # along with this program. If not, see [http://www.gnu.org/licenses/]. """This module contains an object that represents a Telegram KeyboardButton.""" -from typing import TYPE_CHECKING, Final +from typing import TYPE_CHECKING -from telegram import constants from telegram._keyboardbuttonpolltype import KeyboardButtonPollType from telegram._keyboardbuttonrequest import KeyboardButtonRequestChat, KeyboardButtonRequestUsers from telegram._telegramobject import TelegramObject From ce0ec8382bc82dbdff97cb6b57e72efa57c11dba Mon Sep 17 00:00:00 2001 From: OhYoung <212045739+ouyooung@users.noreply.github.com> Date: Sun, 15 Feb 2026 01:47:16 +0800 Subject: [PATCH 10/11] Delete the note about `style` --- src/telegram/_inline/inlinekeyboardbutton.py | 4 ---- src/telegram/_keyboardbutton.py | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/telegram/_inline/inlinekeyboardbutton.py b/src/telegram/_inline/inlinekeyboardbutton.py index e734e59bf20..f36a55c147a 100644 --- a/src/telegram/_inline/inlinekeyboardbutton.py +++ b/src/telegram/_inline/inlinekeyboardbutton.py @@ -157,10 +157,6 @@ class InlineKeyboardButton(TelegramObject): :tg-const:`telegram.KeyboardButtonStyle.GREEN`, and :tg-const:`telegram.KeyboardButtonStyle.RED` are also available. - Note: - This feature requires Telegram client version 6.5.1 or later. Older clients - will display the button without styling. - .. versionadded:: NEXT.VERSION icon_custom_emoji_id (:obj:`str`, optional): Unique identifier of the custom emoji shown before the text of the button. Can only be used by bots that diff --git a/src/telegram/_keyboardbutton.py b/src/telegram/_keyboardbutton.py index 1b757e5dc3a..3af67f96dee 100644 --- a/src/telegram/_keyboardbutton.py +++ b/src/telegram/_keyboardbutton.py @@ -153,10 +153,6 @@ class KeyboardButton(TelegramObject): :tg-const:`telegram.KeyboardButtonStyle.GREEN`, and :tg-const:`telegram.KeyboardButtonStyle.RED` are also available. - Note: - This feature requires Telegram client version 6.5.1 or later. Older clients - will display the button without styling. - .. versionadded:: NEXT.VERSION icon_custom_emoji_id (:obj:`str`): Optional. Unique identifier of the custom emoji shown before the text of the button. Can only be used by bots that From 1b9ff051ae82b8a363cb0a000c82b0a3854b987c Mon Sep 17 00:00:00 2001 From: OhYoung <212045739+ouyooung@users.noreply.github.com> Date: Sun, 15 Feb 2026 17:50:39 +0800 Subject: [PATCH 11/11] Add color parameter tests for KeyboardButton in WithRequest tests --- src/telegram/_inline/inlinekeyboardbutton.py | 6 +----- src/telegram/_keyboardbutton.py | 4 ++-- tests/_inline/test_inlinekeyboardmarkup.py | 21 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/telegram/_inline/inlinekeyboardbutton.py b/src/telegram/_inline/inlinekeyboardbutton.py index f36a55c147a..75ff4a35617 100644 --- a/src/telegram/_inline/inlinekeyboardbutton.py +++ b/src/telegram/_inline/inlinekeyboardbutton.py @@ -148,7 +148,7 @@ class InlineKeyboardButton(TelegramObject): Note: This type of button **must** always be the first button in the first row and can only be used in invoice messages. - style (:obj:`str`): Optional. Style of the button. Determines the visual appearance + style (:obj:`str`, optional): Style of the button. Determines the visual appearance of the button in supported Telegram clients. Only three values are supported: :tg-const:`telegram.KeyboardButtonStyle.PRIMARY` (blue), :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` (green), and @@ -235,10 +235,6 @@ class InlineKeyboardButton(TelegramObject): :tg-const:`telegram.KeyboardButtonStyle.GREEN`, and :tg-const:`telegram.KeyboardButtonStyle.RED` are also available. - Note: - This feature requires Telegram client version 6.5.1 or later. Older clients - will display the button without styling. - .. versionadded:: NEXT.VERSION icon_custom_emoji_id (:obj:`str`): Optional. Unique identifier of the custom emoji shown before the text of the button. Can only be used by bots that diff --git a/src/telegram/_keyboardbutton.py b/src/telegram/_keyboardbutton.py index 3af67f96dee..d38350dfcdb 100644 --- a/src/telegram/_keyboardbutton.py +++ b/src/telegram/_keyboardbutton.py @@ -98,7 +98,7 @@ class KeyboardButton(TelegramObject): Available in private chats only. .. versionadded:: 20.1 - style (:obj:`str`): Optional. Style of the button. Determines the visual appearance + style (:obj:`str`, optional): Style of the button. Determines the visual appearance of the button in supported Telegram clients. Only three values are supported: :tg-const:`telegram.KeyboardButtonStyle.PRIMARY` (blue), :tg-const:`telegram.KeyboardButtonStyle.SUCCESS` (green), and @@ -108,7 +108,7 @@ class KeyboardButton(TelegramObject): :tg-const:`telegram.KeyboardButtonStyle.RED` are also available. .. versionadded:: NEXT.VERSION - icon_custom_emoji_id (:obj:`str`): Optional. Unique identifier of the + icon_custom_emoji_id (:obj:`str`, optional): Unique identifier of the custom emoji shown before the text of the button. Can only be used by bots that purchased additional usernames on Fragment or in the messages directly sent by the bot to private, group and supergroup chats if the owner of the bot has a Telegram diff --git a/tests/_inline/test_inlinekeyboardmarkup.py b/tests/_inline/test_inlinekeyboardmarkup.py index 3de2901ca6f..c13d24367f3 100644 --- a/tests/_inline/test_inlinekeyboardmarkup.py +++ b/tests/_inline/test_inlinekeyboardmarkup.py @@ -239,3 +239,24 @@ async def test_send_message_with_inline_keyboard_markup( ) assert message.text == "Testing InlineKeyboardMarkup" + + async def test_send_message_with_colored_inline_keyboard_button(self, bot, chat_id): + markup = InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton( + text="Colored Button", + callback_data="data1", + style="red", + ) + ] + ] + ) + message = await bot.send_message( + chat_id, + "Testing colored InlineKeyboardButton", + reply_markup=markup, + ) + assert message.text == "Testing colored InlineKeyboardButton" + button = message.reply_markup.inline_keyboard[0][0] + assert button.color == "red"